R Shiny中do.call传...参数时reactive值求值异常如何解决
问题原因
两个核心错误导致参数异常:
do.call调用语法错误:do.call仅第二个参数args接收要传给目标函数的参数列表,原示例里把dots()作为第三个参数传入,根本没有和固定参数合并,自然无法被...捕获。- 响应式值传递逻辑错误:如果参数列表里混入了未求值的reactive对象(比如漏写
()的reactive表达式、未在响应式上下文里取出的input值),没有做Shiny适配的普通函数是无法识别这类特殊对象的。
修复方案
核心原则:所有传入普通自定义函数的参数,必须在传入前完成全部求值,合并为一个完全由普通R对象组成的完整参数列表,再传给do.call。
修正后的可复现代码
library(shiny) ui <- fluidPage( numericInput("x1", "x1", value = 2), numericInput("x2", "x2", value = 2), numericInput("power_dotodotdot_1", "power_x1", value = 2), numericInput("power_dotodotdot_2", "power_x2", value = 2), verbatimTextOutput("res") ) server <- function(input, output) { # 注意:原函数用exists()判断...参数存在逻辑漏洞,已同步修正 makeaverage <- function(x1, x2, ...){ dot_args <- list(...) power_x1 <- if (!is.null(dot_args$power_x1)) dot_args$power_x1 else 1 power_x2 <- if (!is.null(dot_args$power_x2)) dot_args$power_x2 else 1 x1 <- x1^power_x1 x2 <- x2^power_x2 (x1 + x2)/2 } dots <- reactive({ list( power_x1 = input$power_dotodotdot_1, power_x2 = input$power_dotodotdot_2 ) }) output$res <- renderText({ # 合并所有参数,所有响应式值在此处完成求值 all_args <- c( list(x1 = input$x1, x2 = input$x2), dots() ) # 传入完整参数列表 do.call(makeaverage, all_args) }) } shinyApp(ui, server)
对应myReporter场景的写法
按照同样逻辑改造即可,不需要修改原myReporter函数的内部代码:
# 假设par、reports、data都是响应式对象 rpt <- reactive({ all_args <- c( list( reports = reports(), data = data() ), par() # 响应式参数列表加()完成求值 ) do.call(myReporter, all_args) })
注意事项
- 不要用
exists()判断...中是否存在参数,该函数会搜索整个调用环境,若环境中存在同名变量会触发逻辑错误,正确做法是先把...转为列表,再判断对应元素是否非空。 - 所有reactive对象、input值必须在响应式上下文(比如
render*、reactive、observe内部)中通过()完成取值后再加入参数列表,不能直接把reactive对象本身塞进列表。 do.call的args参数必须包含所有要传给目标函数的入参,不要在args外额外传参。
内容的提问来源于stack exchange,提问作者Captain Tyler
相关产品推荐
相关产品推荐

