闪亮的多个相关事件的一个动作按钮

时间:2017-11-18 12:34:02

标签: r shiny

我开发了一个Shiny应用程序,允许用户条件选择一些相关事件。下面是一个非常简化的玩具示例,以帮助说明我的问题/问题。

在我的实际问题中,服务器代码包含多个计算上昂贵的程序,这些程序是可选的运行程序。有一个"基线"必须运行以产生输出的函数,然后firstObject或secondObject将其作为输入,如果用户选择这样做,则产生更多输出。

每个功能最多可能需要30到40分钟。因此,我编写了代码以允许用户使用checkInputBox选择他们想要运行的函数,然后在选择它们之后,有一个操作它们的操作按钮,允许用户离开并让过程完成它的过程很长时间。这比将actionButton与每个可能的事件相关联更方便。

以下代码成功地产生了所有期望的输出。但是,从设计的角度来看,我不确定它是否正确"。在我的玩具示例中,代码很简单,但假设baseObject的代码需要30分钟才能运行。在baseObject运行时,firstObject和secondObject的代码也被执行,因为它们依赖于相同的操作按钮。但是,在完成baseObject的功能之前,他们无法做任何事情。类似地,在firstObject完成之前,secondObject不能执行任何操作。

同样,这一切都有效并产生正确的输出(在我的真实代码和玩具代码中)。但是,是否有一种方法可以维护单个操作按钮,但是对于firstObject不执行任何操作,UNTIL baseline已生成其输出,然后secondObject将等待firstObject在用户选择它时产生其输出。

我担心的是,我在firstObject中创建了额外的计算开销,试图做一些在baseObject完成之前无法做的事情,并且它一遍又一遍地循环直到它能够正确执行。

我知道我可以创建不同的动作按钮。例如,我可以为基线创建一个操作按钮,然后用户可以等到它完成,然后单击firstObject的操作按钮,依此类推。但是,从功能上来说,这不会像真正的问题那样起作用,这允许整个选定的进程运行,这可能需要数小时而且用户不需要在他们的机器前面。

谢谢,我希望这段代码有助于说明我所描述的问题。

ui <- {
  fluidPage(
    h3('Run Stuff'),
    checkboxInput("runModel1", "Model 1"),
    checkboxInput("runModel2", "Model 2"),
    actionButton('runAll', 'Run Models'),
    verbatimTextOutput("out1"),
    verbatimTextOutput("out2")
    )
}

    server <- function(input, output, session) {

baseObject <- eventReactive(input$runAll, {
    if(input$runModel1){
        runif(100)
    }
})

firstObject <- eventReactive(input$runAll, {
    if(input$runModel1){
        runif(100) + baseObject()
    }
})

secondObject <- eventReactive(input$runAll, {
    if(input$runModel2){
        runif(100) + firstObject()
    }
})

output$out1 <- renderPrint({
if (input$runModel1)
    firstObject()
})

output$out2 <- renderPrint({
if (input$runModel2)
    secondObject()
})
} # end server


shinyApp(ui, server) #run 

1 个答案:

答案 0 :(得分:0)

关于反应性表达的两件事要记住:

  1. 反应式表达式是惰性的,只有在被其他东西调用时才会执行。这与观察者不同,观察者在其依赖性发生变化时立即执行。

  2. 缓存活动表达式结果。只要它们的依赖关系没有改变,后续调用就不会导致表达式重新执行,而是检索缓存的值。

  3. 基于这两点,我认为你没有问题,你的例子就是你正在寻找的。勾选两个复选框后,每个响应式表达式只会在每个操作按钮单击时运行一次。

    虽然我可以建议删除eventReactive中不必要的if语句。这将允许用户仅检查runModel2并使其所有依赖项正常运行。下面的修改示例 - 我还添加了一些message(...)语句,以便您可以在R控制台中查看执行流程。

    library(shiny)
    
    ui <- fluidPage(
      h3('Run Stuff'),
      checkboxInput("runModel1", "Model 1"),
      checkboxInput("runModel2", "Model 2"),
      actionButton('runAll', 'Run Models'),
      verbatimTextOutput("out1"),
      verbatimTextOutput("out2")
    )
    
    server <- function(input, output, session) {
    
      baseObject <- eventReactive(input$runAll, {
        message("calculating baseObject...")
        result <- runif(100)
        message("...baseObject done")
        return(result)
      })
    
      firstObject <- eventReactive(input$runAll, {
        message("calculating firstObject...")
        result <- runif(100) + baseObject()
        message("...firstObject done")
        return(result)
      })
    
      secondObject <- eventReactive(input$runAll, {
        message("calculating secondObject...")
        result <- runif(100) + firstObject()
        message("...secondObject done")
        return(result)
      })
    
      output$out1 <- renderPrint({
        if (input$runModel1)
          firstObject()
      })
    
      output$out2 <- renderPrint({
        if (input$runModel2)
          secondObject()
      })
    }
    
    shinyApp(ui, server)