Error handling in Shiny Async/Promise/future

I do not understand how to handle errors in a future. The app below returns an error randomly (by design), but I get a warning Warning: Error in as.promise.default: Don't know how to convert object of class simpleError into a promise, and shiny does not continue.

library(shiny)
library(promises)
library(future)
plan(multiprocess)
set.seed(11)

ui <- fluidPage(# App title ----
                titlePanel("Hello Shiny!"),
                
                # Sidebar layout with input and output definitions ----
                sidebarLayout(# Sidebar panel for inputs ----
                              sidebarPanel(
                                sliderInput(
                                  inputId = "bins",
                                  label = "Number of bins:",
                                  min = 1,
                                  max = 50,
                                  value = 30
                                )
                              ),
                              
                              # Main panel for displaying outputs ----
                              mainPanel(plotOutput(outputId = "distPlot"))))

server <- function(input, output) {
  
  hardWork = function(){
    if (runif(1) < 0.4) {
      stop("No plot data")  
    }
    Sys.sleep(2)
    faithful$waiting 
  }
  
  plotIt = function(x){
    breaks = seq(min(x), max(x), length.out = input$bins + 1)
    hist(x, breaks = breaks)
  }
  
  output$distPlot <- renderPlot({
    future({hardWork()}) %...>% 
      plotIt() %...!%
      catch(print) 
  })
  
}
shinyApp(ui = ui, server = server)

(Same error under Ubuntu)

R version 3.5.0 (2018-04-23)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252    LC_MONETARY=German_Germany.1252
[4] LC_NUMERIC=C                    LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] future_1.8.1        promises_1.0.1.9000 shiny_1.1.0.9000   

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.17      codetools_0.2-15  listenv_0.7.0     crayon_1.3.4      digest_0.6.15    
 [6] later_0.7.2       mime_0.5          R6_2.2.2          jsonlite_1.5      xtable_1.8-2     
[11] magrittr_1.5      rlang_0.2.1       rstudioapi_0.7    Cairo_1.5-9       tools_3.5.0      
[16] rsconnect_0.8.8   httpuv_1.4.3.9002 parallel_3.5.0    compiler_3.5.0    globals_0.11.0   
[21] htmltools_0.3.6

Got it.

  hardWork = function(){
    if (runif(1) < 0.5) {
      promise_reject("Reject")
    } else {
      Sys.sleep(2)
      promise_resolve(faithful$waiting)
    }
  }
  
  plotIt = function(x){
    if (is.null(x)) return(NULL)
    breaks = seq(min(x), max(x), length.out = isolate(input$bins) + 1)
    hist(x, breaks = breaks)
  }
  
  output$distPlot <- renderPlot({
    input$bins 
    hardWork() %...>%  (function(val){
      plotIt(val) 
    }) %...!% 
      {
      message(conditionMessage(.))
      }
  })
  
2 Likes