Hi, I am running the following code, which has 2 buttons, one is for executing Sleep(10) and another to read a csv and populate a datatable. I am keeping the first button execution within future and second button function as usual operation. However when I click on both buttons one after the another, the second button still seems to wait for the Sleep functionality to complete. Any reason or issue with the code below why it is not executing in parallel or async ?
library(promises)
library(shiny)
library(future)
plan(multiprocess)
longRunningFunction <- function(value) {
Sys.sleep(10)
return(value)
}
readFile <- function() {
x <- data.frame()
x=read.delim("./sampledata.txt",header=FALSE,sep=",")
}
ui <- fluidPage(
titlePanel("Async with Promises"),
sidebarLayout(
sidebarPanel(
actionButton("long", "Long running function"),
actionButton("tblButton", "Display table")),
mainPanel(
textOutput("txt"),
shiny::dataTableOutput("result")
)
)
)
server <- function(input, output,session) {
observeEvent(input$long, {
timedelay <- future(longRunningFunction(5))
output$txt <- renderText({
timedelay %...>% print()
})
})
observeEvent(input$tblButton, {
tbl <- readFile()
output$result <- shiny::renderDataTable({
tbl
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
I'm not a Shiny expert, but from reading about how promises supposed to work, I seemed to remember that authors explicitly said that they won't work for single processes (like in your case). They are designed to have an effect only if you have multiple users connecting to your app.
Specifically in your case it would mean that you can open two tabs with the same app and if you press "long" button in one and then "table" button in another, then table should be drawn immediately. I've tested it on my machine and this is exactly how it works.
Also, promises in future
and promises in promises
are not the same thing, unfortunately, so I'm not sure if there is any sense in this case specifically to use future
at all.
1 Like
Yes, it works on different tabs, and I suppose that is the expectation from async with promises.
On the usage of the future package, from the documentation and videos I have gone through, I think it is expected to be used together along with promises package. I don't know if there is promises within future. Calling a function within future starts a new process and promise (%...>%) is used to ensure that any subsequent processing is dependent on the values returned by the function and allowing the main processes to carry on separately. Is this understanding correct? or is there is different usage for promises?
I think you are right, I seemed to forget context of what I read about promises. Specifically I've remembered this bit from the Abstractions for Promise-Based Asynchronous Programming • promises page:
Oh, I’ve heard of promises in R! From the NSE chapter in Hadley’s Advanced R book!
Ah… this is awkward, but no. I’m using the word “promise”, but I’m not referring to that kind of promise. For the purposes of async programming, try to forget that you’ve ever heard of that kind of promise, OK?
I know it seems needlessly confusing, but the promises we’re talking about here are ... directly inspired by a central abstraction in modern JavaScript, and the JS folks named them “promises”.
In my defense, future
package does have the same concept of promise, so we now have 3 places where it is used, so I'm getting cross-eyed
1 Like