Skip to content

Commit c79ba2c

Browse files
authored
Merge pull request #1281 from ropensci/async
Support Shiny async/promises based rendering
2 parents 742a70b + f0c815b commit c79ba2c

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

DESCRIPTION

+3-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ Imports:
4343
rlang,
4444
crosstalk,
4545
purrr,
46-
data.table
46+
data.table,
47+
promises
4748
Suggests:
4849
MASS,
4950
maps,
@@ -52,7 +53,7 @@ Suggests:
5253
testthat,
5354
knitr,
5455
devtools,
55-
shiny (>= 0.14),
56+
shiny (>= 1.1.0),
5657
curl,
5758
rmarkdown,
5859
Rserve,

R/shiny.R

+10-1
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,19 @@ renderPlotly <- function(expr, env = parent.frame(), quoted = FALSE) {
3838
if (!quoted) { expr <- substitute(expr) } # force quoted
3939
# this makes it possible to pass a ggplot2 object to renderPlotly()
4040
# https://github.com/ramnathv/htmlwidgets/issues/166#issuecomment-153000306
41-
expr <- as.call(list(call("::", quote("plotly"), quote("ggplotly")), expr))
41+
expr <- as.call(list(call(":::", quote("plotly"), quote("prepareWidget")), expr))
4242
shinyRenderWidget(expr, plotlyOutput, env, quoted = TRUE)
4343
}
4444

45+
# Converts a plot, OR a promise of a plot, to plotly
46+
prepareWidget <- function(x) {
47+
if (promises::is.promising(x)) {
48+
promises::then(x, ggplotly)
49+
} else {
50+
ggplotly(x)
51+
}
52+
}
53+
4554

4655
#' Access plotly user input event data in shiny
4756
#'

inst/examples/shiny/async/app.R

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
library(shiny)
2+
library(plotly)
3+
library(ggplot2)
4+
library(promises)
5+
library(future)
6+
plan(multisession)
7+
8+
ui <- fluidPage(
9+
plotlyOutput("plot1"),
10+
plotlyOutput("plot2"),
11+
plotlyOutput("plot3"),
12+
plotlyOutput("plot4")
13+
)
14+
15+
server <- function(input, output, session) {
16+
output$plot1 <- renderPlotly({
17+
# Async plot_ly
18+
future({ Sys.sleep(2); cars }) %...>%
19+
plot_ly(x = ~speed, y = ~dist, type = "scatter", mode = "markers")
20+
})
21+
22+
output$plot2 <- renderPlotly({
23+
# Async ggplotly
24+
future({ Sys.sleep(2); mtcars }) %...>%
25+
{ ggplot(., aes(hp, mpg)) + geom_point() } %...>%
26+
ggplotly()
27+
})
28+
29+
output$plot3 <- renderPlotly({
30+
# Not async
31+
plot_ly(iris, x = ~Sepal.Length, y = ~Sepal.Width,
32+
type = "scatter", mode = "markers")
33+
})
34+
35+
output$plot4 <- renderPlotly({
36+
# Ensure errors are handled properly (should be blank)
37+
future({}) %...>%
38+
{ req(FALSE) }
39+
})
40+
}
41+
42+
shinyApp(ui, server)

0 commit comments

Comments
 (0)