The answer by @DSGym works in showing one plot after another but this still does not function asynchronously. In fact if you have a plot which takes a long time to render or a data frame which take a long time to calculate, we need to perform these operations asynchronously. As an example consider this regular shiny app with no asynchronous support,
library(shinydashboard)
library(plotly)
library(future)
library(promises)
plan(multisession)
header <- dashboardHeader(
title = ""
)
body <- dashboardBody(
fluidRow(
column(width = 6,
box(width = NULL, solidHeader = TRUE,
plotly::plotlyOutput("box_plot1")
)
),
column(width = 6,
box(width = NULL, solidHeader = TRUE,
plotly::plotlyOutput("box_plot2")
)
)
)
)
ui <- dashboardPage(
header,
dashboardSidebar(disable = TRUE),
body
)
server <- function(input, output, session) {
output$box_plot1 <- plotly::renderPlotly({
for (i in 1:10) {
print(i)
Sys.sleep(1)
}
plot_ly(ggplot2::diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
layout(boxmode = "group")
})
output$box_plot2 <- plotly::renderPlotly({
for (i in 11:20) {
print(i)
Sys.sleep(1)
}
plot_ly(ggplot2::diamonds, y = ~price, color = ~cut, type = "box")
})
}
shinyApp(ui = ui, server = server)
Each plot counts to 10 and shows its output. The whole operation takes 20+ seconds to complete from when runApp() is executed.
To call both the plots asynchronously we use the futures and promises package.
library(shinydashboard)
library(plotly)
library(future)
library(promises)
plan(multisession)
header <- dashboardHeader(
title = ""
)
body <- dashboardBody(
fluidRow(
column(width = 6,
box(width = NULL, solidHeader = TRUE,
plotly::plotlyOutput("box_plot1")
)
),
column(width = 6,
box(width = NULL, solidHeader = TRUE,
plotly::plotlyOutput("box_plot2")
)
)
)
)
ui <- dashboardPage(
header,
dashboardSidebar(disable = TRUE),
body
)
server <- function(input, output, session) {
output$box_plot1 <- plotly::renderPlotly({
future({
for (i in 1:10) {
print(i)
Sys.sleep(1)
}
plot_ly(ggplot2::diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
layout(boxmode = "group")
})
})
output$box_plot2 <- plotly::renderPlotly({
future({
for (i in 11:20) {
print(i)
Sys.sleep(1)
}
plot_ly(ggplot2::diamonds, y = ~price, color = ~cut, type = "box")
})
})
}
shinyApp(ui = ui, server = server)
Now, even though both plots count up to 10, the plots execute asynchronously. The total time to load the plots reduced to below 20 seconds.
However, both plots still load together. This is because of the inherent flush cycle in shiny. Hence, even if we execute the plots asynchronously, all plots will always load at the same time.
You can read more about this here: https://rstudio.github.io/promises/articles/shiny.html