withCallingHandlers() และการเริ่มทำงานใหม่
ใช้ withCallingHandlers() เพื่อจัดการเงื่อนไขจากบริบทที่ไม่ใช่เฉพาะที่
withCallingHandlers() และการเริ่มทำงานใหม่ เป็นบทเรียน R Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน R Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน
tryCatch เทียบกับ withCallingHandlers
ความแตกต่างสำคัญคือ tryCatch() จะสร้าง การออกจากบริบทแบบไม่ใช่เฉพาะที่ เมื่อดักจับเงื่อนไขได้ การควบคุมจะย้ายออกจากนิพจน์และไม่ย้อนกลับมา ส่วน withCallingHandlers() จะคงสแต็กการเรียกไว้ และสามารถทำงานต่อหลังจัดการเงื่อนไขแล้วได้
# tryCatch: execution does NOT continue after warning
tryCatch({
warning('first')
cat('This line is never reached\n')
}, warning = function(w) cat('tryCatch caught:', w$message, '\n'))withCallingHandlers ทำให้การทำงานดำเนินต่อ
เมื่อใช้ withCallingHandlers() ตัวจัดการจะทำงาน แต่การทำงานจะดำเนินต่อหลังจากมีการส่งสัญญาณเงื่อนไขแล้ว เว้นแต่ว่าตัวจัดการเองจะโยนข้อผิดพลาดหรือเรียกใช้การเริ่มการทำงานใหม่ สแต็กการเรียกจะไม่ถูกคลายออก
withCallingHandlers({
warning('first warning')
cat('Execution continues here\n')
warning('second warning')
cat('And here too\n')
}, warning = function(w) {
cat('Handler saw:', w$message, '\n')
invokeRestart('muffleWarning')
})การเริ่มการทำงานใหม่ muffleWarning
การเรียก invokeRestart('muffleWarning') ภายในตัวจัดการคำเตือนจะระงับไม่ให้ตัวจัดการเริ่มต้นของ R พิมพ์คำเตือนออกมา หากไม่เรียกใช้ หลังจากตัวจัดการของคุณทำงานแล้ว R ก็ยังคงพิมพ์คำเตือนผ่านกลไกเริ่มต้นของตน
# Without muffleWarning: warning still shows after handler
withCallingHandlers({
warning('test')
}, warning = function(w) {
cat('Handler ran\n')
# no muffleWarning: default handler still fires
})การเริ่มการทำงานใหม่ muffleMessage
เช่นเดียวกัน การเรียก invokeRestart('muffleMessage') ภายในตัวจัดการข้อความจะปิดเสียงข้อความหลังจากตัวจัดการแบบกำหนดเองของคุณประมวลผลแล้ว กลไกนี้อยู่เบื้องหลัง suppressMessages()
withCallingHandlers({
message('Progress: 50%')
message('Progress: 100%')
}, message = function(m) {
cat('[LOG]', trimws(m$message), '\n')
invokeRestart('muffleMessage')
})การบันทึกคำเตือนโดยไม่หยุดการทำงาน
การใช้งาน withCallingHandlers() ที่เป็นประโยชน์คือ รวบรวมคำเตือนไว้ในเวกเตอร์บันทึกขณะปล่อยให้โค้ดทำงานจนเสร็จ tryCatch() จะหยุดที่คำเตือนแรก แต่ withCallingHandlers() จะรวบรวมคำเตือนทั้งหมด
warnings_log <- character(0)
result <- withCallingHandlers({
x <- log(-1)
y <- sqrt(-4)
c(x, y)
}, warning = function(w) {
warnings_log <<- c(warnings_log, w$message)
invokeRestart('muffleWarning')
})
cat('Warnings logged:', length(warnings_log), '\n')
cat(warnings_log, sep = '\n')แนวคิดของ invokeRestart()
การเริ่มการทำงานใหม่คือกลยุทธ์การกู้คืนที่กำหนดไว้ล่วงหน้า ซึ่งโค้ดที่ส่งสัญญาณเงื่อนไขสามารถเสนอให้ใช้ได้ invokeRestart(name) จะเลือกหนึ่งในกลยุทธ์เหล่านั้น การเริ่มการทำงานใหม่ที่มีมาให้ ได้แก่ 'muffleWarning' และ 'muffleMessage' และคุณสามารถกำหนดแบบกำหนดเองได้ด้วย withRestarts()
# withRestarts() offers named recovery options
divide_safe <- function(x, y) {
withRestarts(
{
if (y == 0) stop('division by zero')
x / y
},
use_zero = function() 0,
use_na = function() NA
)
}
# A handler can pick a restart
withCallingHandlers(
divide_safe(10, 0),
error = function(e) invokeRestart('use_zero')
)การรวม withCallingHandlers กับ tryCatch
คุณสามารถซ้อนทั้งสองอย่างได้ โดยใช้ withCallingHandlers() ด้านนอกเพื่อบันทึกหรือนับเงื่อนไข และใช้ tryCatch() ด้านในเพื่อจัดเตรียมค่า fallback ตัวจัดการด้านนอกจะเห็นเงื่อนไขก่อน
n_warnings <- 0L
result <- withCallingHandlers(
tryCatch(log(-1), warning = function(w) -999),
warning = function(w) {
n_warnings <<- n_warnings + 1L
cat('Logged warning #', n_warnings, '\n')
}
)
cat('Result:', result, '\n')คลาสเงื่อนไขแบบกำหนดเอง
คุณสามารถสร้างคลาสเงื่อนไขแบบกำหนดเองได้โดยเรียก structure() กับรายการที่มีคลาสเป็น c('myError', 'error', 'condition') ตัวจัดการจะจับคู่ตามคลาส ดังนั้นคลาสแบบกำหนดเองจึงช่วยให้คุณดักจับข้อผิดพลาดเฉพาะประเภทได้โดยไม่ต้องดักจับข้อผิดพลาดทั้งหมด
my_error <- function(msg, data = NULL) {
structure(
class = c('my_error', 'error', 'condition'),
list(message = msg, data = data)
)
}
tryCatch(
stop(my_error('custom error', data = 42)),
my_error = function(e) cat('Custom handler, data=', e$data, '\n'),
error = function(e) cat('Generic handler\n')
)ควรใช้ withCallingHandlers เมื่อใด
ใช้ withCallingHandlers() เมื่อคุณต้องการสังเกตหรือบันทึกเงื่อนไขโดยไม่หยุดการทำงาน ใช้ tryCatch() เมื่อคุณต้องการกู้คืนจากเงื่อนไขและคืนค่าทางเลือก ทั้งสองอย่างใช้แก้ปัญหาคนละแบบ
# withCallingHandlers: observe all, continue
withCallingHandlers(
for (x in c(4, -1, 9, -4)) cat(suppressWarnings(sqrt(x)), ''),
warning = function(w) cat('[warn]', '')
)
cat('\n')สายโซ่การส่งสัญญาณเงื่อนไข
เมื่อมีการส่งสัญญาณเงื่อนไข R จะไล่ขึ้นไปตามสแต็กการเรียกเพื่อค้นหาตัวจัดการ ตัวจัดการของ withCallingHandlers() ทำงานในบริบทแบบพลวัต โดยยังคงสแต็กการเรียกไว้ ส่วนตัวจัดการของ tryCatch() ทำงานหลังจากคลายสแต็กแล้ว จึงไม่เหลือบริบทเดิม
# Demonstrate: withCallingHandlers handler can see full stack
f <- function() {
withCallingHandlers(
g(),
warning = function(w) {
cat('Caught in f, stack length:', sys.nframe(), '\n')
invokeRestart('muffleWarning')
}
)
}
g <- function() warning('from g')
f()การทำงานของ suppressWarnings()
suppressWarnings(expr) มีหลักการเทียบเท่ากับ withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning')) การทำความเข้าใจเรื่องนี้ช่วยให้คุณสร้างรูปแบบของตนเองที่ระงับเฉพาะคำเตือนบางประเภทได้
# Suppress only NaN warnings, not others
suppress_nan_warn <- function(expr) {
withCallingHandlers(expr, warning = function(w) {
if (grepl('NaN', conditionMessage(w)))
invokeRestart('muffleWarning')
})
}
suppress_nan_warn(log(-1)) # NaN warning suppressed
tryCatch(
suppress_nan_warn(warning('other issue')),
warning = function(w) cat('Other warning kept:', w$message, '\n')
)ตรวจสอบอย่างรวดเร็ว
ความแตกต่างหลักระหว่าง withCallingHandlers() กับ tryCatch() คืออะไร
ประเด็นสำคัญของการเริ่มการทำงานใหม่
ประเด็นสำคัญของ withCallingHandlers และการเริ่มการทำงานใหม่:
withCallingHandlers()= ตัวจัดการเฉพาะที่ สแต็กการเรียกยังอยู่ และการทำงานดำเนินต่อได้tryCatch()= การออกจากบริบทแบบไม่ใช่เฉพาะที่ สแต็กถูกคลาย และสามารถคืนค่าทางเลือกได้invokeRestart('muffleWarning')ระงับการพิมพ์คำเตือนตามค่าเริ่มต้นinvokeRestart('muffleMessage')ระงับการพิมพ์ข้อความตามค่าเริ่มต้น- ใช้
withCallingHandlers()เพื่อรวบรวมหรือบันทึกเงื่อนไขทั้งหมดโดยไม่หยุดการทำงาน - คลาสเงื่อนไขแบบกำหนดเองช่วยให้ดักจับข้อผิดพลาดเฉพาะประเภทได้อย่างเลือกเจาะจง
log_vec <- character(0)
withCallingHandlers({
message('start')
warning('low memory')
message('end')
}, message = function(m) {
log_vec <<- c(log_vec, paste('MSG:', trimws(m$message)))
invokeRestart('muffleMessage')
}, warning = function(w) {
log_vec <<- c(log_vec, paste('WARN:', w$message))
invokeRestart('muffleWarning')
})
cat(log_vec, sep = '\n')คำถามที่พบบ่อย
บทเรียน “withCallingHandlers() และการเริ่มทำงานใหม่” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “withCallingHandlers() และการเริ่มทำงานใหม่” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส R Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส R Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “withCallingHandlers() และการเริ่มทำงานใหม่”
ใช้ withCallingHandlers() เพื่อจัดการเงื่อนไขจากบริบทที่ไม่ใช่เฉพาะที่ คุณปฏิบัติ R Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน R Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน R Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “withCallingHandlers() และการเริ่มทำงานใหม่” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน R Academy นี้ได้ไหม
ได้ บทเรียน R Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ข้อผิดพลาด คำเตือน และข้อความใน R
- tryCatch() สำหรับการกู้คืนจากข้อผิดพลาด
- withCallingHandlers() และการเริ่มทำงานใหม่
- การเขียนฟังก์ชันที่ทนทานด้วย stop() และ warning()