Reputation: 707
I have a function in a Shiny app that takes 15-30 seconds to execute. I am using a button to initiate the function, but if a user clicks on it multiple times then the app executes each of the function calls - this can result in the user having to wait multiple minutes for the output. I am noticing that by this time they think the app is hung or broken.
Notice in the reproducible example below that each time you hit the button the app takes 30 seconds to output something. Hitting it multiple times increases that wait time.
Is there a way to stop the execution of code within eventReactive
? Ideally each time the user hits the actionButton
the function stops and executes with the current set of inputs so that the max wait time is only 30 seconds. Is something like that possible?
ui <- fluidPage(titlePanel("actionButton test"),
sidebarLayout(
sidebarPanel(
numericInput(
"n",
"N:",
min = 0,
max = 100,
value = 50
),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel.")
),
mainPanel(verbatimTextOutput("nText"))
))
server <- function(input, output) {
ntext <- eventReactive(input$goButton, {
cat("sleeping for 30 seconds\n")
Sys.sleep(30)
input$n
})
output$nText <- renderText({
ntext()
})
}
shinyApp(ui = ui, server = server)
Upvotes: 0
Views: 749
Reputation: 160417
One alternative is to use shinyjs
to disable (as @StéphaneLaurent suggested) and re-enable.
library(shiny)
library(shinyjs) # NEW
ui <- fluidPage(
shinyjs::useShinyjs(), # NEW
titlePanel("actionButton test"),
sidebarLayout(
sidebarPanel(
numericInput(
"n",
"N:",
min = 0,
max = 100,
value = 50
),
br(),
actionButton("goButton", "Go!"),
p("Click the button to update the value displayed in the main panel.")
),
mainPanel(verbatimTextOutput("nText"))
))
server <- function(input, output) {
ntext <- eventReactive(input$goButton, {
shinyjs::disable("goButton") # NEW
cat("sleeping for 30 seconds\n")
Sys.sleep(30)
shinyjs::enable("goButton") # NEW
input$n
})
output$nText <- renderText({
ntext()
})
}
shinyApp(ui = ui, server = server)
Granted, the shiny interface will still "hang" in a sense, but at least the button will not accept multiple presses. (You might want to consider future
and promise
s.)
Upvotes: 1