强制渲染已计算的反应元素

时间:2015-10-20 16:18:00

标签: r shiny

我正在尝试构建一个闪亮的应用程序,通过不同的render *函数输出多个结果。

问题是其中一个结果需要一些时间来计算。所以我希望能够尽快呈现快速的结果。

以下是一些代码来说明

# ui.R
library(shiny)

shinyUI(fluidPage(
    textOutput("res1"),
    textOutput('res2')
))

# server.R
library(shiny)

shinyServer(function(input, output) {

    output$res1 = renderText({
        "shows up instantly"
    })

    output$res2 = renderText({
            Sys.sleep(3)
            "shows up after 3 sec"
    })
})

目前,网页保持空白状态3秒钟,同时渲染两个元素。

我的问题如下:是否有可能强制output$res1output$res2之前执行,并且在长计算开始之前将其结果发送到浏览器?

2 个答案:

答案 0 :(得分:2)

签出invalidateLater否则,如果您只想渲染文本,可以使用以下方式将文本直接发送到客户端:

# ui.R
library(shiny)

ui <- shinyUI(fluidPage(
  tags$head(
    tags$script(
      HTML("
            Shiny.addCustomMessageHandler ('print',function (message) {
              $('#'+message.selector).html(message.html);
              console.log(message);
            });
           ")
    )
  ),
  textOutput("res1"),
  textOutput('res2')
))

# server.R
server <- shinyServer(function(input, output, session) {
  session$sendCustomMessage(type = 'print', message = list(selector = 'res1', html = "shows up instantly"))
  Sys.sleep(3)
  session$sendCustomMessage(type = 'print', message = list(selector = 'res2', html = "shows up after 3 sec"))
})

shinyApp(ui = ui, server = server)

答案 1 :(得分:2)

我找到了解决方法。我们的想法是强制所有render*函数在启动长计算之前将结果发送到浏览器。

在以下代码中,两个文本区域立即显示,第二个文本区域在3秒后更新。

shinyServer(function(input, output,session) {

    status=reactiveValues(res1IsDone=FALSE,res2HasRendered=FALSE)

    output$res1 = renderText({
        status$res1IsDone = TRUE
        "shows up instantly"
    })

    output$res2 = renderText({
        if(isolate(!status$res1IsDone || !status$res2HasRendered)) {
            status$res2HasRendered = TRUE
            invalidateLater(100,session)
            "wait"
        } else {
            Sys.sleep(3)
            "shows up after 3 sec"

        }
    })
})

根据我的理解,闪亮是单线程的,一旦所有render*函数执行一次(或者所有失效都被解决了?),结果就会被发送回浏览器。