1

I was experimenting promises and as I understand, as pointed out in this issue, an async process running for the same user is supposed to block execution of all other intra-session activities. However this doesn't seem to be a universal principle.

In the example app below, I have an artificially drawn out plotting operation and some other elements to see how they interact. One of these elements is a downloadButton/downloadHandler pair. While the async operation is running, it is still possible to press the downloadButton and get an output, which was unexpected for me. My questions are:

  • Can I stop downloadHandler from being active while an async process is running?
  • Why is downloadHandler special?


library(future)
library(promises)
library(shiny)
plan(multisession)

server = function(input, output) { # slow async plot output$slow_plot <- renderPlot({ input$slow_plot_button future({ print('I am slow') Sys.sleep(10) runif(20) }) %...>% plot(.) }) # fast normal plot output$fast_plot = renderPlot({ print('I am fast') input$fast_plot_button plot(runif(20)) }) # something that has no UI output observeEvent(input$non_ui_update,{ print('Button press yay!') }) # trigger happy downloadHandler output$download = downloadHandler('file', content = function(file){ cat('is a file',file = file) })}

ui = fluidPage( titlePanel("Async test"), sidebarLayout( sidebarPanel( actionButton('slow_plot_button','slow plot button'), actionButton('fast_plot_button','fast plot button'), actionButton('non_ui_update','non ui update'), downloadButton('download','download') ), mainPanel( plotOutput("slow_plot"), plotOutput("fast_plot") ) ) )

shinyApp(ui,server)

Edit: Removed additional information about downloadButton downloading the whole page at first as it is not an integral part of the question

OganM
  • 2,543
  • 16
  • 33
  • Any idea how it has access to reactive variables from the main session? Because as far as I know sessions created by future can't do that. – OganM Oct 24 '18 at 18:58
  • I deleted my previous comment because I'm not sure if it's technically correct, I don't know how internally downloads are handled. I've always assumed a different session because it's a new page that opens up, but now I realize that perhaps that's not correct, maybe the same session is being used, which is what allows you to use any variables easily. – DeanAttali Oct 24 '18 at 19:40
  • hmm that kinda breaks the accepted answer as well. Without knowing further only solution I can think of is to manually disable other buttons and re-enable at promise completion via `finally` but this is not scalable – OganM Oct 24 '18 at 19:53
  • I deleted my answer since it didn't answer your question :). Also, I believe the file download is handled in the same session as well, but I bet it being a separate HTTP request has something to do with the different behavior. – greg L Oct 25 '18 at 01:24
  • If your download handler depends on data that's calculated asynchronously, you could at least prevent the handler from writing content until the future is complete. For example, `content = function(file) data() %...>% cat(file = file)`. Then you wouldn't have to disable buttons. The download handler would block until the async operations it depends on are complete. – greg L Oct 25 '18 at 01:31

0 Answers0