我想继续刷新直到 10:05,在 10:05 之后我得到了tplus0_dt并停止处理 invalidaterLater((。
在 10:00 之前,tplus0_dt不存在,所以我需要一直重新刷新到 10:05。在 10:05 之后,无需重新调整,当tplus0_dt变得非常严重时,invalidaterLater(( 将影响 table1 的显示,屏幕和绘图每 1 秒变为灰色,因此在更新发生时页面看起来已经死了。
那么我该怎么做才能停止处理 invalidateLater(( 并在 10:05 之后继续显示数据呢?感谢您的帮助!我的示例代码如下。
require(shiny)
require(data.table)
app <- shinyApp(
server = function(input, output, session){
get_tplus0_data <- reactive({
time <- substr(as.character(Sys.time()), 12, 16)
invalidateLater(1000)
if(time >= "10:05"){
# tplus0_dt<-data.table(read.csv("/data/df_highest_after_signal.csv",header = T, sep = ",", stringsAsFactors = F))
tplus0_dt<- data.table(a = c(1, 2, 3, 4), b = c(3, 4, 5, 8))
return(tplus0_dt)
}
})
output$table1 <- renderTable({get_tplus0_data()})
},
ui = fluidPage( tableOutput("table1") )
)
runApp(app)
虽然你永远不会从 Shiny 文档中意识到这一点,但invalidateLater()
实际上只返回到你的反应式一次。它似乎反复返回的原因是,在每次行程中,invalidateLater()
函数都会再次运行。
因此,解决方案是在函数周围使用条件,这样您就不会重复调用它:
if(runMeAgain) {
invalidateLater(n)
}
runMeAgain = TRUE # your reactive re-runs every n milliseconds
runMeAgain = FALSE # your reactive does not re-run
另请注意:
-
invalidateLater()
是非阻塞的(其他代码可以在等等( -
invalidateLater()
不会阻止其余的反应运行。如果要在代码中的该点停止反应,请在invalidateLater()
之后放置一个return()
-
invalidateLater()
isolated()
observeEvent()
或eventReactive()
,因此不起作用; 您必须使用observe()
或reactive()
。它也可以在渲染函数中工作,但我从来没有理由尝试过。
就原始问题而言,反应式应该如下所示:
get_tplus0_data <- reactive({
time <- substr(as.character(Sys.time()), 12, 16)
if(time >= "10:05"){
tplus0_dt<- data.table(a = c(1, 2, 3, 4), b = c(3, 4, 5, 8))
return(tplus0_dt)
} else {
invalidateLater(1000)
return()
}
})
您如何根据需要覆盖该功能?
如果在控制台中输入invalidateLaterNew
,则会打印函数的代码。
要覆盖包中的函数,这篇文章将有所帮助: 覆盖在命名空间中导入的函数
然后,您必须考虑函数.getReactiveEnvironment()
和timerCallbacks()
在命名空间之外无法访问。但你可以这样称呼它们:shiny:::.getReactiveEnvironment()
把它放在一起:
您添加了一个附加参数(例如 update
(,这将使您能够随时停止invalideLater()
。
invalidateLaterNew <- function (millis, session = getDefaultReactiveDomain(), update = TRUE)
{
if(update){
ctx <- shiny:::.getReactiveEnvironment()$currentContext()
shiny:::timerCallbacks$schedule(millis, function() {
if (!is.null(session) && session$isClosed()) {
return(invisible())
}
ctx$invalidate()
})
invisible()
}
}
unlockBinding("invalidateLater", as.environment("package:shiny"))
assign("invalidateLater", invalidateLaterNew, "package:shiny")
例:
我使用?invalidateLater
中给出的示例来演示效果:(invalidateLater
将在input$n
大于 800 时停止。因此,您可以根据时间限制调整此示例(。我决定不使用您的时间限制示例,因为测试;)不会那么方便
ui <- fluidPage(
sliderInput("n", "Number of observations", 2, 1000, 500),
plotOutput("plot")
)
server <- function(input, output, session) {
observe({
# Re-execute this reactive expression after 1000 milliseconds
invalidateLater(1000, session, input$n < 800)
# Do something each time this is invalidated.
# The isolate() makes this observer _not_ get invalidated and re-executed
# when input$n changes.
print(paste("The value of input$n is", isolate(input$n)))
})
# Generate a new histogram at timed intervals, but not when
# input$n changes.
output$plot <- renderPlot({
# Re-execute this reactive expression after 2000 milliseconds
invalidateLater(2000, session, input$n < 800)
hist(rnorm(isolate(input$n)))
})
}
shinyApp(ui, server)