r - Shiny中观察者的执行顺序
问题描述
目标和当前方法
我有一个模块,它可以删除自己的 UI。我还希望能够从模块外部调用此终止功能,因此我将一个额外的响应传递给模块的服务器逻辑,并在此响应触发时调用终止例程。
到现在为止还挺好。现在我想实现一个函数,它首先杀死我的模块的所有实例,然后添加这个模块的新实例,这就是我为我选择的设计而苦苦挣扎的地方。
问题
我需要的是,在我的input$add5
观察者添加任何新实例之前,所有旧实例都被杀死。这可以通过设置来完成kill_switch(TRUE)
,但问题是observer
在我的模块中的 可以对此做出反应之前,input$add5
观察者继续添加新模块,这将重置kill_switch
为FALSE
并且基本上旧实例永远不会被杀死。
基本上,在当前的设计中,我希望observer
onkill_switch
在我更改标志后立即做出反应,并且只有在完成此操作后,我的add5
观察者才会继续。
我需要的
我认为我的设计不是最优的,因此任何关于如何设置主应用程序和模块之间接口的建议都将受到高度赞赏。
代码
library(shiny)
boxer_ui <- function(id) {
ns <- NS(id)
div(
id,
id = ns("killme"),
style = "background-color:steelblue; font-size: xx-large; color: white")
}
boxer <- function(input, output, session, kill_switch) {
ns <- session$ns
observe({
req(kill_switch())
removeUI(paste0("#", ns("killme")))
})
}
ui <- fluidPage(actionButton("new", "new"),
actionButton("killall", "Kill All"),
actionButton("add5", "Kill All & Add 5"),
fluidRow(id = "content"))
server <- function(input, output, session) {
ids <- reactiveVal(0)
kill_switch <- reactiveVal(FALSE)
handler <- reactiveValues()
add_new <- function() {
kill_switch(FALSE)
ids(ids() + 1)
new_id <- paste0("id", ids())
insertUI("#content", "beforeEnd", boxer_ui(new_id))
handler[[new_id]] <- callModule(boxer, new_id, kill_switch)
}
observeEvent(input$new, {
isolate({
add_new()
})})
observeEvent(input$add5, {
isolate({
kill_switch(TRUE)
replicate(5, add_new())
})})
observeEvent(input$killall, kill_switch(TRUE))
}
shinyApp(ui, server)
解决方案
我能想到的一种解决方案是拆分remove
/add
如下:
server <- function(input, output, session) {
ids <- reactiveVal(0)
kill_switch <- reactiveVal(FALSE)
add5 <- reactiveVal(FALSE)
handler <- reactiveValues()
add_new <- function() {
kill_switch(FALSE)
ids(ids() + 1)
new_id <- paste0("id", ids())
insertUI("#content", "beforeEnd", boxer_ui(new_id))
handler[[new_id]] <- callModule(boxer, new_id, kill_switch)
}
observeEvent(input$new, {
isolate({
add_new()
})})
observeEvent(input$add5, {
isolate({
kill_switch(TRUE)
add5(TRUE)
})})
observe({
req(add5())
isolate({
replicate(5, add_new())
add5(FALSE)
})
})
observeEvent(input$killall, kill_switch(TRUE))
}
然而,这是基于observer
永远不会被任何其他人打断的假设observer
。真的吗?在这种情况下,我还可以添加priority
参数以确保observer
首先触发内部。
任何人都可以证明我的假设是正确的吗?
推荐阅读
- javascript - 将 ember js 应用程序与反应主机连接:微前端
- javascript - JS:如何在 insertBefore() 之后得到通知?
- apache-kafka - 使用 filebeat 输出 azure eventthub 服务
- ios - Swift 线程安全数组
- sql - 根据优先级 ID 从一组中获取最低日期
- python - 如何在 PowerShell 输出流中正确反映回车?
- html - 孩子的高度为 100%,父母没有高度(以像素为单位)
- python - 远程访问 node.js
- angular - ngx-charts、ng2-charts - ng 12.2.7、chart.js 3.6.0、bootstrap 5.1.1 - 无济于事
- docker - 似乎可以降低 docker 容器