当数据发生变化时,如何阻止在函数中创建的观察者多次存在?
更新:
- 进一步简化了 github 上的应用程序,以便于测试。- 一直在尝试使用destroy
----
我制作了一个应用程序,在整个程序中需要多个(10ish)版本的绘图,因此我编写了 2 个函数:
myplotly
创建地块mypopup
它创建包含属于图中每个粒子的脉冲形状图的弹出窗口,以及弹出窗口中的myplotly
选项按钮modaldialog
,以及所属的观察者
当用户点击第一个图表中的一个点时,这些对话框就会打开。
此函数的缩短版本如下所示:
mypopup <- function(THEDATAFRAME, THEPLOT, THEGROUP, THEPULSEFRAME) {
..... bla bla lots more code in real app.....
..... one example of an observer with only 1 of the arguments needed for this one
observeEvent(input[[paste("Close", THEPLOT, sep ='.')]], {
removeModal()
}, ignoreInit = T)
}
函数*1在创建或加载相应的数据帧时调用,并在数据更改时再次调用。
我面临的问题是,在更改数据并且用户单击一个点后,弹出窗口和所有观察者都会触发两次。如果数据再次更改,弹出窗口会触发 3 次,依此类推。以及基于旧数据的弹出窗口不了解图中现在有超过 1 个集群,因此如果单击集群 2 或 3,错误/NA 绘图等。
声明:
- 使用obs$destroy可能会解决问题,但并不容易(见脚注*2)
- 为什么我们首先要得到双重观察者?修复症状是一回事,理解为什么它们不被简单地覆盖对我来说仍然是一个谜。
我创建了一个工作代码的精简示例以及一些运行它的文件,所有这些都可以在以下 github 链接上找到: https ://github.com/madmark81/Observer-Madness
脚注
1我之所以将其编写为函数,是因为我每次在我的主应用程序中多次应用这种绘图和弹出窗口的组合,具体取决于基本数据帧和脉冲数据帧的独特组合以及包含组 ID 的列和组名。
2 Maximilian 提出了使用将观察者分配给变量的想法。但是这个实现必须在 mypopup 函数之外完成,我无法让它在使用超过 1 个输入参数的观察者上工作,通常由 mypopup 函数的 4 个输入参数排序, 但不能像以下示例那样使用 lapply 调用来完成,该示例恰好有 1 个输入参数:
lapply(plot.list, function(x){
o <- observeEvent(event_data("plotly_click", source = paste("plotlyplot", x, sep = '.')), {
print('clicked')
if(values[[paste("particle_viewer", x, sep = "_")]]) {
## when click in plot: Highlight the clicked particle with java, but also store the clicked point
values[[paste("HLval", x, sep = "_")]] <- event_data("plotly_click", source = paste("plotlyplot", x, sep = '.')) ## this code stores the last clicked point so that the point stays active when object is re-rendered
}
})
})
每次更改数据时都会调用destroy。
observeEvent( values$TrainDFLogged, {
lapply(c("o"), function(x) {
if (exists(x))
{get(x)$destroy
print('destroyed2')
}
})
mypopup(values$TrainDFLogged, "SecondFile", "default", values$TrainPulses)
})
更新 2
但是,当在 mypopup 函数代码之外创建观察者时,似乎不需要销毁并分配给“o”,只在我刚刚发现的时间观察到点击。lapply
所以也许我们应该简单地找到一种方法来在一个或mapply
风格的解决方案中创建所有的观察者,但在mypopup
代码之外?