You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链式调用Shiny Gadget:如何基于返回值触发运行另一个Gadget

解决Shiny Gadget间基于返回值自动启动的问题

问题场景

我有两个可返回值的Shiny Gadget,期望实现:关闭第一个Gadget后,根据其返回值自动启动第二个;关闭第二个Gadget后,根据返回值再启动第一个。但当前递归调用的代码无法实现该需求,且需要不依赖rstudioapi::sendToConsole()的通用方案,触发逻辑必须放在Gadget外部。

原代码如下:

library(shiny)

app1 <- shinyApp(
  fluidPage(
    "app1",
    checkboxInput("launch", "launch app2"),
    actionButton("done", "done")
  ),
  function(input, output, session) {
    observeEvent(input$done, {
      stopApp(input$launch)
    })
  }
)

app2 <- shinyApp(
  fluidPage(
    "app2",
    checkboxInput("launch", "launch app1"),
    actionButton("done", "done")
  ),
  function(input, output, session) {
    observeEvent(input$done, {
      stopApp(input$launch)
    })
  }
)

run_app1 <- function() {
  ret <- runGadget(app1, viewer = dialogViewer("app1"))
  if (ret) run_app2()
}

run_app2 <- function() {
  ret <- runGadget(app2, viewer = dialogViewer("app2"))
  if (ret) run_app1()
}

问题原因

runGadget()是阻塞式函数,直接在启动函数内递归调用另一个启动函数时,当前Gadget的运行上下文未完全释放,导致新的Gadget无法正常初始化启动。

解决方案

使用later包的later()函数延迟启动下一个Gadget,确保当前Gadget的运行环境完全释放后再执行启动逻辑。这是不依赖RStudio的通用方案,且触发逻辑完全在Gadget外部。

修改后的代码:

library(shiny)
library(later)

app1 <- shinyApp(
  fluidPage(
    "app1",
    checkboxInput("launch", "launch app2"),
    actionButton("done", "done")
  ),
  function(input, output, session) {
    observeEvent(input$done, {
      stopApp(input$launch)
    })
  }
)

app2 <- shinyApp(
  fluidPage(
    "app2",
    checkboxInput("launch", "launch app1"),
    actionButton("done", "done")
  ),
  function(input, output, session) {
    observeEvent(input$done, {
      stopApp(input$launch)
    })
  }
)

run_app1 <- function() {
  ret <- runGadget(app1, viewer = dialogViewer("app1"))
  if (ret) {
    # 延迟0.1秒启动,确保当前Gadget上下文完全释放
    later(run_app2, delay = 0.1)
  }
}

run_app2 <- function() {
  ret <- runGadget(app2, viewer = dialogViewer("app2"))
  if (ret) {
    later(run_app1, delay = 0.1)
  }
}

运行run_app1()后,勾选"launch app2"并点击done关闭app1,会自动启动app2;在app2中勾选"launch app1"并关闭后,也会自动启动app1,完全符合需求。

内容的提问来源于stack exchange,提问作者DeanAttali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:15:42