【问题标题】:Is there any way to pre-cache output in Shiny?有没有办法在 Shiny 中预缓存输出?
【发布时间】:2021-08-18 22:52:43
【问题描述】:

我有下面的 Shiny 应用程序。我第一次选择任何给定的数字时,加载结果需要 3 秒。由于bindCache,如果我稍后选择相同的数字,我会立即得到结果。

但是,我不想手动选择所有 10 个数字,只是为了让我的应用在呈现之前做出响应。有没有办法提前缓存一组输入?在此示例中,我想缓存 input$num 值 1 到 10 的结果。在实际应用中,大约有 5 个输入,每个输入有 5 个可能的值,用于缓存 25 个可能的结果。

library(shiny)

ui <- fluidPage(
  sliderInput('num', 'Pick a number:', min = 1, max = 10, value = 1),
  textOutput('out')
)

server <- function(input, output, session) {
 output$out <- reactive({
   Sys.sleep(3)
   paste("Your number is:", input$num)
 }) %>% bindCache(input$num)
}

shinyApp(ui, server)

注意:

一种反应可能是我应该手动预先计算这些结果。在真正的应用程序中,大部分时间来自gt::render_gtgt::gt_output 我提前创建的gt 表。我相信这些函数只能在响应式上下文中使用(意味着只能在 Shiny 应用中使用?)

编辑:

作为旁注,我最初的问题是通过使用gt::as_raw_html 在闪亮应用程序之前的一步中呈现表格来解决的。仍然留下这个问题,因为它有时在其他情况下是一个问题。

【问题讨论】:

  • Joe Cheng 在 RStudio 会议 (2019) 中谈到了在 R Shiny 应用程序中缓存结果作为获得巨大性能提升的一种方式。所以这个谈话可能有你想要的。本次讲座视频为youtube.com/watch?v=Wy3TY0gOmJw&ab_channel=RStudio

标签: r shiny


【解决方案1】:

如何使用持久缓存,运行应用程序一次,根据需要手动更改所有输入(我还包括一个自动化版本,我不太满意,b/c race条件可能发生),然后在随后的运行中,您已正确缓存了所有值?

library(shiny)
library(magrittr)
## change path to a non temp diretcory to keep that even after reboot
shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), 
                                        "myapp-cache")))

xl <- 1:3
yl <- 1:3

ui <- fluidPage(
   sliderInput("x", "x", min(xl), max(xl), min(xl), 1),
   sliderInput("y", "y", min(yl), max(yl), min(yl), 1),
   verbatimTextOutput("z"),
   actionButton("fill", "Fill Cache")
)

server <- function(input, output, session) {
   idx <- idy <- 1
   r <- reactive({
      message("Doing  expensive computation...")
      Sys.sleep(2) ## simulate expensive op
      input$x + input$y
   }) %>% bindCache(input$x, input$y)

   observe({
      req(input$fill)
      if (idx != length(xl) + 1 || idy != length(yl)) {
         ## need the invalidateLater approach 
         ## to allow shiny reacting on the change
         ## not sure whether we cannot trip over race conditions
         ## recommendation: do it once by hand (it's persistent anyways ;)
         invalidateLater(500, session) 
         if (idx == length(xl) + 1) {
            message("Updating y:", idy)
            idx <<- 1
            idy <<-  idy + 1
            updateSliderInput(session, "y", value = yl[[idy]])
         } else {
            message("Updating x:", idx)
            updateSliderInput(session, "x", value = xl[[idx]])
            idx <<- idx + 1
         }
      }
   })

   output$z <- renderText(r())
}

## Start app and set all values
shinyApp(ui, server)

## Close app and restart
## Cache is now filled
shinyApp(ui, server)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 2020-03-17
    • 2020-08-27
    • 2014-11-12
    相关资源
    最近更新 更多