Render plotly在Shining app中异步打印

Render plotly在Shining app中异步打印,r,asynchronous,shiny,promise,plotly,R,Asynchronous,Shiny,Promise,Plotly,在Shining应用程序中,我一次渲染两个绘图,但它们只有在计算完所有绘图后才会渲染。例如,如果渲染9个打印中的8个打印需要8秒,渲染9个打印需要15秒,则前8个打印将仅在渲染9个打印后显示(15秒后而不是8秒后)。见下面的例子 box\u plot1仅在呈现box\u plot2时显示。我玩了一点闪亮的承诺,但到目前为止还没有找到解决办法 MWE: library(shinydashboard) library(plotly) header <- dashboardHeader(

在Shining应用程序中,我一次渲染两个绘图,但它们只有在计算完所有绘图后才会渲染。例如,如果渲染9个打印中的8个打印需要8秒,渲染9个打印需要15秒,则前8个打印将仅在渲染9个打印后显示(15秒后而不是8秒后)。见下面的例子

box\u plot1
仅在呈现
box\u plot2
时显示。我玩了一点闪亮的承诺,但到目前为止还没有找到解决办法

MWE:

library(shinydashboard)
library(plotly)

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({
    p <- plot_ly(ggplot2::diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
      layout(boxmode = "group")

    p
  })

  output$box_plot2 <- plotly::renderPlotly({

    for (i in 1:3) {
      print(i)
      Sys.sleep(1)
    }

    plot_ly(ggplot2::diamonds, y = ~price, color = ~cut, type = "box")
  })
}

shinyApp(ui = ui, server = server)
库(ShinydaShashboard)
图书馆(绘本)

header您可以将
renderUI
与保持计算顺序的
reactiveValues
结合使用

library(shinydashboard)
library(plotly)

header <- dashboardHeader(
    title = ""
)

body <- dashboardBody(
    fluidRow(
        column(width = 6,
               uiOutput("plot1")
        ),
        column(width = 6,
               uiOutput("plot2")
        )
    )
)

ui <- dashboardPage(
    header,
    dashboardSidebar(disable = TRUE),
    body
)

server <- function(input, output, session) {

    rv <- reactiveValues(val = 0)


    output$plot1 <- renderUI({

        output$box_plot1 <- plotly::renderPlotly({

            for (i in 3:5) {
                print(i)
                Sys.sleep(1)
            }

            p <- plot_ly(ggplot2::diamonds, x = ~cut, y = ~price, color = ~clarity, type = "box") %>%
                layout(boxmode = "group")
            rv$val <- 1
            p
        })

        return(
            tagList(
                box(width = NULL, solidHeader = TRUE,
                    plotly::plotlyOutput("box_plot1")
                )
            )
        )

    })



    output$plot2 <- renderUI({

        if(rv$val == 0) {
            return(NULL)
        }

        output$box_plot2 <- plotly::renderPlotly({

            for (i in 1:3) {
                print(i)
                Sys.sleep(1)
            }

            plot_ly(ggplot2::diamonds, y = ~price, color = ~cut, type = "box")
        })

        return(
            tagList(
                box(width = NULL, solidHeader = TRUE,
                    plotly::plotlyOutput("box_plot2")
                )
            )
        )

    })



}

shinyApp(ui = ui, server = server)
库(ShinydaShashboard)
图书馆(绘本)

header由@DSGym给出的答案可以一个接一个地显示图形,但仍然不能异步运行。事实上,如果您有一个需要很长时间渲染的绘图或一个需要很长时间计算的数据帧,我们需要异步执行这些操作。作为一个例子,考虑这个没有任何异步支持的规则闪亮的应用程序,

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)
现在,即使两个图的计数都达到了10,这些图也是异步执行的。加载绘图的总时间减少到20秒以下

但是,两个图仍然一起加载。这是因为光泽中固有的冲洗周期。因此,即使异步执行绘图,所有绘图都将始终同时加载


您可以在这里了解更多信息:

这是不可能的,因为Shining中固有的事件循环,它被烘焙到Shining服务器的设计中。您可以在此处的“刷新周期”下了解更多有关信息:
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)