这是一个如何在闪亮的应用程序中使用未来包的解决方案.当运行计算密集型任务或等待sql查询完成时,可能有多个会话没有会话阻塞另一个会话.我建议打开两个会话(只需在两个选项卡中打开http://127.0.0.1:14072/)并使用按钮来测试功能.
run_app.R
:
library(shiny) library(future) library(shinyjs) runApp(host = "127.0.0.1", port = 14072, launch.browser = TRUE)
ui.R
:
ui <- fluidPage( useShinyjs(), textOutput("existsFutureData"), numericInput("duration", "Duration", value = 5, min = 0), actionButton("start_proc", h5("get data")), actionButton("start_proc_future", h5("get data using future")), checkboxInput("checkbox_syssleep", label = "Use Sys.sleep", value = FALSE), h5('Table data'), dataTableOutput('tableData'), h5('Table future data'), dataTableOutput('tableFutureData') )
server.R
:
plan(multiprocess) fakeDataProcessing <- function(duration, sys_sleep = FALSE) { if(sys_sleep) { Sys.sleep(duration) } else { current_time <- Sys.time() while (current_time + duration > Sys.time()) { } } return(data.frame(test = Sys.time())) } #fakeDataProcessing(5) ############################ SERVER ############################ server <- function(input, output, session) { values <- reactiveValues(runFutureData = FALSE, futureDataLoaded = 0L) future.env <- new.env() output$existsFutureData <- renderText({ paste0("exists(futureData): ", exists("futureData", envir = future.env)," | futureDataLoaded: ", values$futureDataLoaded) }) get_data <- reactive({ if (input$start_proc > 0) { shinyjs::disable("start_proc") isolate({ data <- fakeDataProcessing(input$duration) }) shinyjs::enable("start_proc") data } }) observeEvent(input$start_proc_future, { shinyjs::disable("start_proc_future") duration <- input$duration # This variable needs to be created for use in future object. When using fakeDataProcessing(input$duration) an error occurs: 'Warning: Error in : Operation not allowed without an active reactive context.' checkbox_syssleep <- input$checkbox_syssleep future.env$futureData %<-% fakeDataProcessing(duration, sys_sleep = checkbox_syssleep) future.env$futureDataObj <- futureOf(future.env$futureData) values$runFutureData <- TRUE check_if_future_data_is_loaded$resume() }, ignoreNULL = TRUE, ignoreInit = TRUE ) check_if_future_data_is_loaded <- observe({ invalidateLater(1000) if (resolved(future.env$futureDataObj)) { check_if_future_data_is_loaded$suspend() values$futureDataLoaded <- values$futureDataLoaded + 1L values$runFutureData <- FALSE shinyjs::enable("start_proc_future") } }, suspended = TRUE) get_futureData <- reactive({ if(values$futureDataLoaded > 0) future.env$futureData }) output$tableData <- renderDataTable(get_data()) output$tableFutureData <- renderDataTable(get_futureData()) session$onSessionEnded(function() { check_if_future_data_is_loaded$suspend() }) }