闪亮-并行渲染多个输出

时间:2019-01-15 15:03:34

标签: r parallel-processing shiny future shiny-reactivity

当我要渲染链接到单个观察者的多个输出时,将在计算两个输出之后渲染它们。如果输出之间的计算很长,则显示所有输出需要很长时间。

在Shiny应用程序中是否可以单独或并行渲染链接到单个观察者的输出?无需等待渲染,直到计算出所有输出。

示例

library(shiny)

ui <- fluidPage(
  actionButton('button', 'klik'),
  textOutput('first'),
  textOutput('second')
)

server <- function(input, output, session) {
  observeEvent({input$button},{
    output$first <- renderText({Sys.Date()})
    Sys.sleep(10)
    output$second <- renderText({Sys.Date()})
  })
}

shinyApp(ui, server)

1 个答案:

答案 0 :(得分:0)

由于@BertilBaron,我找到了一种避免在R-Shiny中等待较长计算的方法。我使用的文章可以在here中找到。

基本上,您要做的是使用软件包future并行运行每个进程。使用此软件包,每次用户单击按钮时,将执行计算。因此请记住,您必须为不耐烦的用户构建块。

我的工作示例

library(shiny)
library(promises)
library(future)
plan(multiprocess)

ui <- fluidPage(
  actionButton('button', 'klik'),
  textOutput('first'),
  textOutput('second')
)

server <- function(input, output) {
  nclicks <- reactiveVal(0)
  nclicks2 <- reactiveVal(0)
  result_val <- reactiveVal()
  result_val2 <- reactiveVal()

  observeEvent(input$button,{
    # Don't do anything if analysis is already being run
    if(nclicks() != 0 | nclicks2() != 0){
      showNotification("Already running analysis")
      return(NULL)
    }

    # Increment clicks and prevent concurrent analyses
    nclicks(nclicks() + 1)
    nclicks2(nclicks2() + 1)

    result <- future({
      # Long Running Task
      Sys.sleep(10)

      #Some results
      Sys.time()
    }) %...>% result_val()

    result2 <- future({
      #Some results
      Sys.time()
    }) %...>% result_val2()

    # Catch inturrupt (or any other error) and notify user
    result <- catch(result,
                    function(e){
                      result_val(NULL)
                      print(e$message)
                      showNotification(e$message)
                    })
    result2 <- catch(result2,
                    function(e){
                      result_val2(NULL)
                      print(e$message)
                      showNotification(e$message)
                    })

    # After the promise has been evaluated set nclicks to 0 to allow for anlother Run
    result <- finally(result,
                      function(){
                        nclicks(0)
                      })
    result2 <- finally(result2,
                      function(){
                        nclicks2(0)
                      })

    # Return something other than the promise so shiny remains responsive
    NULL
  })

  output$first <- renderText({
    req(result_val())
  })
  output$second <- renderText({
    req(result_val2())
  })
}

# Run the application 
shinyApp(ui = ui, server = server)