Shiny - 并行渲染多个输出

Shiny - Render multiple outputs in parallel

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

是否可以在 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)

感谢@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)