我正在尝试构建一个闪亮的应用程序,通过不同的 render* 函数输出多个结果。
问题是其中一个结果需要一些时间来计算。所以我希望shiny能够尽快渲染出快速的结果。
这是一些代码来说明
# 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"
})
})
Run Code Online (Sandbox Code Playgroud)
目前,网页保持空白 3 秒,两个元素同时呈现。
我的问题如下:是否可以强制output$res1执行之前output$res2并将其结果发送到浏览器之前进行长时间的计算开始?
我找到了一个解决方法。这个想法是迫使所有人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"
}
})
})
Run Code Online (Sandbox Code Playgroud)
render*据我了解,shiny 是单线程的,一旦所有函数执行一次(或者所有失效都解决了?),结果就会发送回浏览器。