rshinyshiny-reactivity

Getting a user input into a future function


I am building an shiny app, where users upload a bunch of data and than choose which should be computed. The computation itself is rather timeconsuming and should be stored in a list. To keep shiny responsive during the calculation (for the user and other users) I tried to utilize promises and future. The problem is that I am not able to get an input into future function. I always get Warning: Error in $: Can't access reactive value 'mem_pos' outside of reactive consumer. i Do you need to wrap inside reactive() or observe()? [No stack trace available]. I tried to read about reactive but I am simply stuck.

Here is a minimal example of the problem (to display it, the list has only one value each):

library(shiny)
library(promises)
library(future)

plan(multisession)

# example function
subfct = function(n) {
  Sys.sleep(3)
  return(n*2)
}

# shiny page
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      numericInput("mem_pos", min = 1, max = 30, value = 1, label="mem pos"),
      actionButton("mem_button", label="set mem value")
    ),
    mainPanel(
      tableOutput("result")
    )
  )
)

server <- function(input, output) {
  superval = reactiveValues(mem = rep(list(0), 10))
  
  # set the future calculations
  observeEvent(input$mem_button, {future({return(subfct( input$mem_pos ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) # here lies the problem

  # show result table
  observe( {output$result = renderTable({unlist(superval$mem)})})
}

# Run the application 
shinyApp(ui = ui, server = server)

If the problematic line is exchanged by observeEvent(input$mem_button, {future({return(subfct( 5 ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) it basically works. But I am not able to get the user input into the function. I am grateful for a direct help or an explanation of reactive for my specific problem.


Solution

  • I solved it. Not enterily sure why, but isolate does the trick. This code works for me:

    library(shiny)
    library(promises)
    library(future)
    
    plan(multisession)
    
    # example function
    subfct = function(n) {
      Sys.sleep(3)
      return(n*2)
    }
    
    # shiny page
    ui <- fluidPage(
      sidebarLayout(
        sidebarPanel(
          numericInput("mem_pos", min = 1, max = 30, value = 1, label="mem pos"),
          actionButton("mem_button", label="set mem value")
        ),
        mainPanel(
          tableOutput("result")
        )
      )
    )
    
    server <- function(input, output) {
      superval = reactiveValues(mem = rep(list(0), 10))
      
      # set the future calculations
      observeEvent(input$mem_button, {future({return(subfct( isolate(input$mem_pos)  ))}) %...>% {superval$mem[[input$mem_pos]] = .}}) # here lied the problem 
      
      # show result table
      observe( {output$result = renderTable({unlist(superval$mem)})})
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)