我在Shiny中创建了一个包含15个数据表的仪表板。每个表都从API中提取数据,此过程需要一些时间。所以我想一次将每个表输出到ui,以便用户可以读取第一个表而其他表加载。但似乎Shiny始终保持所有输出,直到服务器功能完成执行。有没有办法改变这个?
答案 0 :(得分:2)
我曾经遇到类似的应用问题。我所做的是在另一个R会话中进行花费很多时间的计算。也许现在有些软件包可以让它变得更容易,但这就是我解决它的方法:
您可以制作由observeEvent
触发的actionButton
。在此观察者中,您启动另一个R会话(例如,系统调用Rscript
)。
然后,当后台的R会话正在进行所有计算时,应用程序仍然响应。
要从后台进程检索信息,您可以使用闪亮的reactivePoll
功能。
在您的情况下,后台R会话将对每个表执行处理,并在完成表后将结果写入文件。 reactivePoll
会注意这些文件。一旦出现这样的文件,reactivePoll
函数就可以读取它并将其显示为被动。然后可以某种方式呈现此反应的值以供用户查看。
这样,每个表都会逐个处理,而应用程序仍然具有响应能力,并且能够在后台进程仍在运行时显示结果。
这是一个显示原则的应用程序。
library(shiny)
# batch process communicates via file
write("", "tmp.info")
# cheap function to check for results
cheap <- function() scan("tmp.info", what = "")
shinyServer(function(input, output, session) {
# start process
observeEvent(input$go, {
system2("Rscript", args = c("batch.r", input$num1, input$num2),
stdout = "", stderr = "", wait = FALSE)
})
# watch file
watch <- reactivePoll(500, NULL, cheap, cheap)
# retrieve result from batch process
result1 <- reactive(if(length(watch()) > 0) watch()[1] else NULL)
result2 <- reactive(if(length(watch()) > 1) watch()[2] else NULL)
# show results
output$add <- renderPrint(result1())
output$multiply <- renderPrint(result2())
})
library(shiny)
shinyUI(fluidPage(sidebarLayout(
sidebarPanel(
h2("Add and multiply"),
numericInput("num1", "Number 1", value = 1),
numericInput("num2", "Number 2", value = 1),
helpText("Both numbers are added, and multiplied. Each calculation takes 4 sec."),
br(),
actionButton('go', 'Start')
),
mainPanel(
h4("Result of Addition"),
verbatimTextOutput("add"),
h4("Result of Multiplication"),
verbatimTextOutput("multiply")
)
)))
# read info
args <- commandArgs(TRUE)
args <- as.numeric(args)
# add
res <- args[1] + args[2]
Sys.sleep(4)
write(res, "tmp.info")
# mult
res <- args[1] * args[2]
Sys.sleep(4)
write(res, "tmp.info", append = TRUE)
quit(save = "no")
server.r ui.r和batch.r必须位于同一目录中。一个文件&#34; tmp.info&#34;创建用于通信。结果直接从该文件中读取,batch.r以输入作为参数启动。您也可以使用所有文件。