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)
当我想渲染链接到单个观察者的多个输出时,它们是在计算完两个输出后渲染的。如果输出之间的计算时间很长,则需要很长时间才能显示所有输出。
是否可以在 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)