I've written code that runs a long calculation in which, as part of it, several UI elements are updated showing part of the progress and results of the calculations. I would like to make possible for the user to run more than one calculation at the same time and keep been able of checking the progress and results.
This is an example app code:
#EXAMPLE APP----
#Libraries----
library(shiny)
library(shinyjs)
#UI code----
ui <- fluidPage(
useShinyjs(),
sidebarLayout(
sidebarPanel(
actionButton(
'pressme',
'Press me'
)
),
mainPanel(
div(
id='inmainP'
)
)
)
)
#Server code----
server <- function(input, output, session) {
clicks <- reactiveValues()
clicks$count <- 0
##Adding the UI elements necesary when pressing the button----
observeEvent(input$pressme,{
clicks$count <- clicks$count + 1
insertUI(
'#inmainP',
'beforeEnd',
div(id=paste0('Pcontainer',clicks$count),
p(tags$b(paste0(clicks$count,'-Process'))),
style = 'border:solid thin black;text-align: center;')
)
insertUI(
paste0('#Pcontainer',clicks$count),
'beforeEnd',
textOutput(paste0('process',clicks$count,'1'))
)
insertUI(
paste0('#Pcontainer',clicks$count),
'beforeEnd',
textOutput(paste0('process',clicks$count,'2'))
)
insertUI(
paste0('#Pcontainer',clicks$count),
'beforeEnd',
textOutput(paste0('process',clicks$count,'3'))
)
###Creating input to observe to do long calculation----
#This is done because it is the only way that I've accomplished, in the real app,
#that new elements render before starting calculation
runjs(
paste0('
Shiny.setInputValue("start",',clicks$count,')
')
)
})
##Runing long calculation----
observeEvent(input$start,{
odd <- 1
even <- 1
for (i in 1:10) {
Sys.sleep(1)
html(paste0('process',clicks$count,'1'), i)
if((i%%2)==0){
html(paste0('process',clicks$count,'2'), even)
even <- even + 1
}else{
html(paste0('process',clicks$count,'3'), odd)
odd <- odd + 1
}
}
})
}
shinyApp(ui, server)
As you will notice this app runs perfectly but new processes only run once the ones before have finished. I would like to solve this using callr package, that I've managed to use in other long jobs in the app, but don't know how to use it properly here. Any other suggestions based on the use of other packages as promises or future are also welcome.
As I mention I've tried to solve this using callr but I've failed at traying to create eventReact(s) programmatically, necessary to run each background job (to my understanding). And I don't understand how to make UI update from background process. How do the background processes work in R?
Link to this question in stackoverflow: