闪亮的承诺未来不会在事件上起作用 [英] Shiny promises future is not working on eventReactive

查看:71
本文介绍了闪亮的承诺未来不会在事件上起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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)

我做错了什么?

解决方案

欢迎使用!

线程讨论了相同的问题.

另请参阅GitHub上的Joe Cheng的详细 answer .

>

您遇到的主要问题反映在他的以下陈述中:

至少对于此版本的Shiny,目标是不允许这样做 会话间的一种响应,而是会话间的响应; IE., 运行异步操作不会使自己的会话更多 反应灵敏,但可以让其他会话更加活跃 响应的.

但是,有一些方法可以通过在后台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>

I have an inputButton than when you click it, 2 querys to mysql database are done. One is a heavy one (more than 10 secs) and the other is light (less than 0.01sec to get data).

As I want to show the result of this querys on shiny app, I have intendeed to use Promises and Future packages for asyncronous loading.

In the example that I show you of my code, I have simulated the SQL querys with the function heavyFunction, which is intended to simulate the heavy query and the ligth one time loads.

The issue is that this code is not working for me, because the results of the light query are not shown till the heavy query is done.

Note: In the Rstudio console, this code works perfect...

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)

What I'm doing wrong?

解决方案

Welcome to SO!

This thread discusses the same issue.

Please also see the detailed answer from Joe Cheng on GitHub.

The main problem you are experiencing is reflected by his following statement:

The goal, at least for this release of Shiny, is not to allow this kind of intra-session responsiveness, but rather, inter-session; i.e., running an async operation won't make its owning session more responsive, but rather will allow other sessions to be more responsive.

However, there are ways to work around this behaviour by running the future in a background R process with e.g. library(callr) or more convenient library(future.callr) and it's plan(callr).

Here is a working version of your code:

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)

The most important point here is to realize, that you shouldn't return your future directly, otherwise it will block all other actions - the observer returns nothing, it only has the side-effect of triggering the callback-function.

这篇关于闪亮的承诺未来不会在事件上起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆