【问题标题】:Unable to render "loading" using Shiny and futures无法使用 Shiny 和期货渲染“加载”
【发布时间】:2019-08-13 09:11:06
【问题描述】:

我正在尝试使用期货来显示“加载”图标。这是我的代码

library(shiny)
library(promises)
library(future)
plan(multiprocess) 

disksUI <- function(id) {
  ns <- NS(id)
  fluidRow(
    box(
      uiOutput(ns("loading")),
      dataTableOutput(ns("filelist")),
      width=12
    )
  )
}

disksServer <- function(input, output, session) {
  state <- reactiveValues(onLoading=FALSE)

  observe({
    if (state$onLoading) {
      output$loading <- renderUI("Loading")
    } else {
      output$loading <- renderUI("Done")
    }
  })

  filelist <- reactive(
    {
      state$onLoading <- TRUE
      future({
        Sys.sleep(3)
        state$onLoading <- FALSE
       }
      )
    }
  )

  output$filelist <- renderDataTable({
    filelist()
  })

}

但是,结果不是我所期望的。我期待的是

  • 字符串Loading 立即出现
  • 三秒后,字符串 Loading 被替换为 Done

会发生什么

  • 三秒钟内什么都没有写。
  • 三秒后,加载字符串出现。

【问题讨论】:

  • 我建议探索一下 shinycssloaders 包 - 在加载内容时提供微调器,而不是被其他需要加载的内容所阻碍。
  • @Megan 那个包使用了一个技巧。微调器总是在那里,它只是在一个使其不可见的 z-index 处,并希望它出现,因为重新绘制会使顶层消失,这不是我的情况。此外,它没有使用任何期货。这不是解决旋转器问题。它是关于理解如何处理上述用例(在异步请求后添加新的 UI 元素),它在 React 中有效。

标签: r shiny future


【解决方案1】:

我首先发布了我的答案here。但是,也将其添加到此处以供将来的读者使用:

这是一个工作示例:

library(shiny)
library(shinydashboard)
library(promises)
library(future)
library(shinyjs)
plan(multiprocess)

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

  output$loading <- renderUI("Idling")

  myFilelist <- reactiveVal(NULL)

  observeEvent(input$getBtn, {

    disable("getBtn")
    output$loading <- renderUI("Loading")

    myFuture <- future({
      Sys.sleep(3)
      data.frame(list.files(getwd()))
    })

    then(myFuture, onFulfilled = function(value) {
      enable("getBtn")
      output$loading <- renderUI("Done")
      myFilelist(value)
    },
    onRejected = NULL)

    return(NULL)
  })

  output$filelist <- renderDataTable({
    myFilelist()
  })

}

ui <- fluidPage(
  useShinyjs(),
  fluidRow(
    actionButton("getBtn", "Get file list"),
    box(
      uiOutput("loading"),
      dataTableOutput("filelist"),
      width=12
    )
  )
)

shinyApp(ui, server)

请注意observeEvent() 中的return(NULL) - 这是对自己的会话隐藏未来 - 允许会话内响应。但是,现在我们必须处理潜在的比赛条件,正如 Joe Cheng 已经向您提到的 here。在这个简单的示例中,我们可以禁用触发按钮,以避免用户在其他人仍在处理时创建新期货的可能性。 更多详情请阅读this

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多