R Shiny reactiveValues()和invalidateLater()的奇怪行为

时间:2015-06-11 10:15:22

标签: r shiny

我有一个用例可视化仪表板的操作数据。我希望它可以在数据添加到数据库时定期更新可视化。我想到的逻辑是首先检查实时数据库表中的行数是否等于R中相应数据帧中的行数。如果是,则不需要提取数据,如果没有,则从中提取数据数据库。我想要避免的是定期提取数据(实际数据库表有超过500万行),无论是否有新数据。

我创建了数据here的子集。下面的代码我写了一个概念证明,首先介绍invalidateLater()reactiveValues()在R中的工作原理以及如何使用它们。它只是读取数据库表中的行数并将其显示给用户。如果行数更改,则使用新行数更新用户界面。请注意,要重现,您可能希望将数据放入数据库,以便模拟添加和删除行以查看" app"的反应。我使用了postgres和ODBC连接。如果按原样运行代码,您会注意到当行添加到数据库时,当应用程序执行检查时,用户界面(textOutput()窗口小部件)将灰显几秒钟并且似乎是在最终正确显示新行数之前处于冥想状态。这是使用代码,该代码首先检查数据库与R中保存的值之间的行号是否存在差异。

但是,如果我注释掉检查差异的部分代码(注释掉下面的块)

sharedValues$data <- if(!is.null(sharedValues$data)){
      if(nrow(sqlFetch(conn2,"test2")) == sharedValues$data){
        return(sharedValues$data)
      }
    }
    else{
      sharedValues$data <- nrow(sqlFetch(conn2,"test2"))
      return(sharedValues$data)
    }

而是只是定期提取数据,无论是否有变化(取消注释此行)

#sharedValues$data <- nrow(sqlFetch(conn2,"test2"))

界面反应非常好,没有延迟(窗口小部件文本变灰),新的行值显示在用户界面上。

我的问题是导致&#34;滞后的&#34;在进行昂贵的数据库选择查询之前运行第一个检查数据库更改的第一个备选方案(这是所需的备选方案)时的行为,但是当修改代码以提取数据而不管数据库更改(这对我来说效率低)这种滞后那种丑陋的行为让人头疼吗?整个代码如下:

library(shiny)
library(shinydashboard)
library(rCharts)
library(curl)
library(RODBC)

conn2 <- odbcConnect("postgres") # database connection object

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    fluidRow(
      box(textOutput("text1"),width = 6)
    )
  )
)

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

  sharedValues <<- reactiveValues()
  observe({
    invalidateLater(30000,session)   
    cat("updating data...\n")
    sharedValues$data <- if(!is.null(sharedValues$data)){
      if(nrow(sqlFetch(conn2,"test2")) == sharedValues$data){
        return(sharedValues$data)
      }
    }
    else{
      sharedValues$data <- nrow(sqlFetch(conn2,"test2"))
      return(sharedValues$data)
    }

     #sharedValues$data <- nrow(sqlFetch(conn2,"test2"))
  })

  output$text1 <- renderText({

    y <- sharedValues$data
    return(y)

  })  

}

shinyApp(ui, server)

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

根据this回答,这可以通过在ui.R中操纵CSS来解决。

tags$style(type="text/css",
  ".recalculating { opacity: 1.0; }"
)