如何在Shiny应用中捕获并显示Plumber API的运行消息?
解决Plumber API运行消息在Shiny中展示的方案
要实现Shiny实时接收并展示Plumber API中slow_function的运行步骤,核心是让API流式输出消息,再让Shiny监听这个流来更新UI,完全不需要前端依赖目标R包。
1. 修改Plumber API端点(支持流式消息输出)
修改plumber.R,让/msg端点使用Server-Sent Events(SSE) 格式实时发送运行步骤,同时捕获slow_function的message输出:
# plumber.R library(plumber) slow_function <- function() { for (i in 1:5) { message(paste0("Step: ", i)) Sys.sleep(1) # 模拟耗时操作 } return("任务完成") } # 定义流式响应的msg端点 #* @get /msg #* @serializer contentType list(type="text/event-stream") function(res) { # 捕获slow_function的message输出 withCallingHandlers({ slow_function() }, message = function(m) { # 按SSE格式封装消息(必须以data: 开头,结尾加\n\n) sse_msg <- paste0("data: ", gsub("\n", "", m$message), "\n\n") res$write(sse_msg) res$flush() # 立即发送缓冲区内容,不等待函数执行完毕 invokeRestart("muffleMessage") # 阻止消息默认输出到控制台 }) # 发送任务完成信号 res$write("data: 任务完成\n\n") res$flush() }
2. 修改Shiny应用(监听流式消息并更新UI)
使用httr2的流式请求功能,实时接收API发送的SSE消息,通过自定义消息更新Shiny界面:
# app.R library(shiny) library(httr2) ui <- fluidPage( titlePanel("API运行步骤展示"), verbatimTextOutput("step_log") ) server <- function(input, output, session) { # 初始化步骤日志 step_log <- reactiveVal(c()) # 发起流式请求并处理消息 observe({ req <- request("http://localhost:8000/msg") %>% req_headers(Accept = "text/event-stream") %>% req_stream(function(line) { # 解析SSE消息,提取data内容 if (grepl("^data: ", line)) { new_step <- sub("^data: ", "", line) # 更新日志 step_log(c(step_log(), new_step)) # 发送自定义消息更新UI session$sendCustomMessage("update_log", step_log()) } }) # 执行请求 req_perform(req) }) # 监听自定义消息,实时渲染日志 observeEvent(input$update_log, { output$step_log <- renderPrint({ cat(paste(input$update_log, collapse = "\n")) }) }) } shinyApp(ui, server)
关键说明
- SSE格式:Plumber端必须按
data: 消息内容\n\n的格式发送,这是SSE的标准格式,Shiny端才能正确解析。 - 流式响应:
res$flush()确保每个步骤消息立即发送,而不是等slow_function执行完才返回所有内容。 - 无依赖:Shiny只需要和Plumber API通信,完全不需要加载
slow_function所在的R包。
内容的提问来源于stack exchange,提问作者det
相关产品推荐
相关产品推荐

