R Shiny进度条与脚本执行同步问题求助
解决方案
问题分析
你的代码存在两个核心问题:
- 进度条动画会先执行完10次来回滚动,才开始运行脚本,这意味着脚本执行时进度条已经停止,不符合你“进度条持续滚动至脚本完成”的需求;
- 脚本未执行大概率是路径问题——Shiny应用的工作目录可能和你预期的不一致,导致找不到
./Scripts/Scenarios.R文件。
修复步骤与代码
1. 先确认脚本路径正确性
在server函数开头添加代码,打印当前工作目录,确认脚本路径是否存在:
server <- function(input, output, session) { print(getwd()) # 打印当前工作目录 # 后续代码... }
如果输出的目录下没有Scripts/Scenarios.R,请改用绝对路径(比如source("C:/Projects/MyShinyApp/Scripts/Scenarios.R")),或者用normalizePath确保路径正确:
source(normalizePath("./Scripts/Scenarios.R", mustWork = TRUE))
mustWork = TRUE会在路径不存在时直接报错,帮你快速定位问题。
2. 重构代码实现“进度条持续滚动至脚本完成”
由于Shiny是单线程应用,直接在主线程同时做进度条动画和脚本执行会导致阻塞,需要用future + promises包实现异步执行:
第一步:安装并加载依赖包
install.packages(c("future", "promises")) library(shiny) library(future) library(promises) # 设置异步后端为multisession plan(multisession)
第二步:修改server中的observeEvent代码
observeEvent(input$calc_tax_prop_Button, { progress <- shiny::Progress$new() on.exit(progress$close()) progress$set(message = "Running Simulation", detail = "Please wait...", value = 0) # 标记脚本是否执行完成 is_done <- reactiveVal(FALSE) # 异步执行目标脚本 future({ # 这里替换为正确的脚本路径 source(normalizePath("./Scripts/Scenarios.R", mustWork = TRUE)) return(TRUE) }) %...>% { # 脚本执行完成后标记状态 is_done(TRUE) } %>% catch(function(err) { # 捕获脚本执行错误,显示通知 showNotification(paste("Error:", err$message), type = "error", duration = NULL) is_done(TRUE) }) # 持续更新进度条,直到脚本完成 observe({ req(!is_done()) # 进度条来回滚动 for (j in seq(0, 1, by = 0.1)) { if (is_done()) break progress$set(value = j) Sys.sleep(0.1) } for (j in seq(1, 0, by = -0.1)) { if (is_done()) break progress$set(value = j) Sys.sleep(0.1) } # 循环触发自身,持续更新 invalidateLater(100) }) # 脚本完成后显示通知 observe({ req(is_done()) showNotification("Simulation is done!", duration = NULL) # 停止进度条更新的observe cancelObservers() }) })
代码说明
- 用
future把脚本执行放到后台线程,避免阻塞主线程的进度条更新; is_done作为状态标记,控制进度条的循环更新;- 添加错误捕获,脚本执行出错时会弹出错误通知;
- 进度条会持续来回滚动,直到脚本执行完成(无论成功或失败)。
内容的提问来源于stack exchange,提问作者silent_hunter
相关产品推荐
相关产品推荐

