为何使用catch/then处理future_promise错误仍显示“Unhandled”?
future_promise错误处理后仍提示"Unhandled"且工作进程未释放的解决方法
问题复现代码
library(future) library(promises) plan(multicore, workers = 3) Sys.getpid() # [1] 1270066 nbrOfFreeWorkers() # [1] 3 thisproc <- promises::future_promise({ setTimeLimit(elapsed = 2, transient = TRUE) Sys.sleep(3) 1L }, seed = TRUE) %>% promises::then( function(val) { message("survived: ", val) val }) %>% catch( function(error) { message("terminated: ", substring(conditionMessage(error), 1, 16)) NULL })
出现的问题
- 已通过
catch()处理错误(打印了terminated: Unexpected resul),但仍输出Unhandled promise error提示 - 错误信息被重复报告两次
- 执行
nbrOfFreeWorkers()返回2,需手动调用resetWorkers(plan())才能恢复为3
问题原因
该问题源于future与promises包的版本兼容性:在future 1.30.0与promises 1.2.0.1的组合下,当future因超时被强制终止时,返回的结果为NULL,不符合promises预期的FutureResult类型,导致错误处理逻辑未正确标记rejectionHandled,进而触发未处理错误的二次提示;同时异常终止的工作进程未被自动回收。
解决方案
方案1:升级future包(推荐)
future 1.31.0已修复该结果类型不匹配的问题,执行以下命令升级:
install.packages("future")
升级后重新运行代码:
- 错误处理逻辑会正常标记
rejectionHandled,不再出现Unhandled promise error提示 - 工作进程会自动释放,
nbrOfFreeWorkers()返回3,无需手动重置 - 错误仅被
catch()处理一次,无重复报告
方案2:临时兼容处理(无法升级时)
若无法升级future包,需在catch()中返回符合要求的FutureResult对象,而非NULL,同时手动处理工作进程回收:
thisproc <- promises::future_promise({ setTimeLimit(elapsed = 2, transient = TRUE) Sys.sleep(3) 1L }, seed = TRUE) %>% promises::then( function(val) { message("survived: ", val) val }) %>% catch( function(error) { message("terminated: ", substring(conditionMessage(error), 1, 16)) # 返回标准FutureResult对象 structure(list(result = NULL, condition = error), class = "FutureResult") }) # 手动回收残留的异常工作进程 if (nbrOfFreeWorkers() < plan()$workers) { resetWorkers(plan()) }
内容的提问来源于stack exchange,提问作者r2evans
相关产品推荐
相关产品推荐

