r语言 - 从函数中使用反应性(在Shiny中)



我正在为我的应用程序编写一个函数,该函数将在后台调用一个进程,并监视它停止的时刻。在关闭会话时,进程应该被终止,所以我希望它在函数外部可用。如果我用<<-符号分配进程,会发生一些奇怪的事情…

library(shiny)
library(processx)

runAsync <- function() {
mainProcess <<- process$new("sleep", "10")
procTimer <- reactivePoll(1000, NULL, 
checkFunc = function() 
mainProcess$is_alive() ,
valueFunc = function() 
mainProcess$is_alive()
)

observeEvent(procTimer(),  {
if(procTimer()) {print("Begin")} else {print("End")}
print(  mainProcess)
})
}

ui <- fluidPage(
actionButton("runBtn", "Run async process"),
)
server <- function(input, output, session) {
observeEvent(input$runBtn, runAsync())  
}
shinyApp(ui, server)

第一次点击按钮,一切都按预期工作。输出为

[1] "Begin"
PROCESS 'sleep', running, pid #####.
[1] "End"
PROCESS 'sleep', finished.

第二次调用时,observeEvent被触发两次。第三次调用时,会触发三次observedEvent。等等......第三次点击按钮时输出为

PROCESS 'sleep', running, pid 19228.
[1] "Begin"
PROCESS 'sleep', running, pid 19228.
[1] "Begin"
PROCESS 'sleep', running, pid 19228.
[1] "End"
PROCESS 'sleep', finished.
[1] "End"
PROCESS 'sleep', finished.
[1] "End"
PROCESS 'sleep', finished.

如果我用一个简单的<-赋值代替<<-赋值,那就修复了它(至少在表面上),问题就不会发生了。

所以,我的主要问题是这种行为的原因是什么?我想要理解.

我还想问一个附带的问题:对于这样的功能,什么是好的设计?在函数中启动reactivePoll是一种好做法吗?

问题是,每次调用runAsync()时,您都会添加一个新的observeEvent调用,快速修复将引入一个响应值,检查该函数是否已被调用,然后不添加新的observeEvent,如该示例所示:

library(shiny)
library(processx)

runAsync <- function(start) {

mainProcess <<- process$new("sleep", "10")

procTimer <- reactivePoll(1000, NULL, 
checkFunc = function() 
mainProcess$is_alive() ,
valueFunc = function() 
mainProcess$is_alive()
)
if(isTRUE(reactive_value$start))
{
observeEvent(procTimer(),  {
if(procTimer()) {print("Begin")} else {print("End")}
print(  mainProcess)
})
reactive_value$start <- FALSE
}
}
ui <- fluidPage(
actionButton("runBtn", "Run async process"),
)
reactive_value <- shiny::reactiveValues(start = TRUE)
server <- function(input, output, session) {
observeEvent(input$runBtn, runAsync(reactive_value))  
}
shinyApp(ui, server)

较长的解决方案是重构代码,使observeEvent调用位于runAsync函数之外

最新更新