我有一个inputButton,当您单击它时,完成了对mysql数据库的2个查询。一个是较重的(超过10秒),另一个是较轻的(少于0.01秒以获取数据)。
由于我想在闪亮的应用程序上显示此查询的结果,因此我打算使用Promises和Future包进行异步加载。
在向您展示代码的示例中,我已经使用功能 heavyFunction 模拟了SQL查询,该函数旨在模拟重载查询和一次加载的ligth。
问题在于此代码对我不起作用,因为在完成繁重的查询之前,不会显示轻度查询的结果。
注意:在Rstudio控制台中,此代码可以完美运行...
library(future)
library(promises)
plan(multiprocess)
heavyFunction <- function(n){
Sys.sleep(n)
print(n)
}
ui <- fluidPage(
actionButton("go","Show the data"),
textOutput("result0sec"),
textOutput("result10sec")
)
server <- function(input,output,session){
data0 <- eventReactive(input$go,{
heavyFunction(0)
})
data10 <- eventReactive(input$go,{
heavyFunction(10)
})
output$result0sec <- renderText({
data <- data0()
future(data)%...>%print()
})
output$result10sec <- renderText({
data <- data10()
print(data)
})
}
shinyApp(ui,server)
我做错了什么?
答案 0 :(得分:3)
欢迎您!
This主题讨论了相同的问题。
另请参阅Joe Cheng在GitHub上提供的详细answer。
您遇到的主要问题反映在他的以下陈述中:
至少对于此版本的Shiny,目标是不允许这样做 会话间的一种响应,而是会话间的响应;即 运行异步操作不会使自己的会话更多 反应灵敏,但可以让其他会话更加活跃 响应的。
但是,有一些方法可以通过在后台R进程中运行Future来解决此问题,例如library(callr)
或更方便的library(future.callr)
,它是plan(callr)
。
这是您代码的有效版本:
library(future)
library(promises)
library(future.callr)
plan(callr)
heavyFunction <- function(n) {
Sys.sleep(n)
print(n)
}
ui <- fluidPage(
br(),
actionButton("go", "Show the data"),
br(), br(),
textOutput("result0sec"),
textOutput("result10sec")
)
server <- function(input, output, session) {
futureData <- reactiveValues(data10 = NULL)
data0 <- eventReactive(input$go, {
heavyFunction(0)
})
observeEvent(input$go, {
myFuture <- future({
heavyFunction(5)
})
then(
myFuture,
onFulfilled = function(value) {
futureData$data10 <<- value
},
onRejected = NULL
)
return(NULL)
})
output$result0sec <- renderText({
data0()
})
output$result10sec <- renderText({
req(futureData$data10)
})
}
shinyApp(ui, server)
这里最重要的一点是要意识到,您不应该直接返回自己的未来,否则它将阻止所有其他操作-观察者什么也不返回,它只具有触发回调函数的副作用。 / p>