Блестящие обещания будущего не работают на eventReactive - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть inputButton, чем когда вы нажимаете на него, 2 запроса к базе данных mysql выполнены.Один из них тяжелый (более 10 секунд), а другой - легкий (менее 0,01 секунды для получения данных).

Поскольку я хочу показать результат этого запроса в блестящем приложении, я хотелиспользуйте пакеты Promises и Future для асинхронной загрузки.

В примере, который я показываю вам из своего кода, я смоделировал SQL-запросы с помощью функции heavyFunction , которая предназначена для имитации тяжелого запроса и однократной загрузки.

Проблема в том, что этот код не работает для меня, потому что результаты простого запроса не отображаются, пока не будет выполнен тяжелый запрос.

Примечание. В консоли 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)

Что я делаю не так?

1 Ответ

0 голосов
/ 21 ноября 2018

Добро пожаловать в SO!

В этой теме обсуждается та же проблема.

Пожалуйста, также посмотрите подробный ответ от Джо Чена на GitHub.

Основная проблема, с которой вы сталкиваетесь, отражена в его следующем утверждении:

Цель, по крайней мере для этого выпуска Shiny, - не допустить такого рода внутрисессионного реагированияа точнее межсессионный;то есть, выполнение асинхронной операции не сделает свой собственный сеанс более отзывчивым, а скорее позволит другим сеансам быть более отзывчивым.

Однако есть способы обойти это поведение, запустив будущеев фоновом процессе R, например, с 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)

Самый важный моментздесь нужно понимать, что вы не должны возвращать свое будущее напрямую, иначе оно заблокирует все другие действия - наблюдатель ничего не возвращает, у него есть только побочный эффект запуска функции обратного вызова.

...