繁体   English   中英

如何追踪事件监听器的添加位置?

[英]How do I track down where event listener is getting added?

我有一个相当好的javascript(有react / redux但没有jquery)代码库用于我正在构建的webapp,我注意到当我在UI中反复打开和关闭某个面板时,监听器的数量根据Chrome的性能时间表不断增加。

该图如下所示: 时间线图

我已经允许chrome的性能监视器运行一两分钟,页面处于空闲状态(在打开/关闭面板之后),希望听众可能会收集垃圾,但事实并非如此。 我在这个过程中切换到其他选项卡,也希望听众在选项卡背景时收集垃圾,但不幸的是,他们不会。

因此,我怀疑有些听众正在注册,但从未注册过。

这引出了两个主要问题:

  1. 我的假设是听众是否会得到补充并且从未被束缚似乎是明智的,或者我可以采取更多措施来证实这种怀疑?
  2. 假设我的怀疑是正确的,我怎样才能最好地追踪添加事件监听器的代码? 我已经尝试过以下方法:
    • 查看负责打开相关面板的代码,查看它添加任何侦听器的位置,并注释掉这些部分以查看性能图中是否有任何更改。 没有变化。
    • 像这样重写addEventListener原型:

var f = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, fn, capture) {
    this.f = f;
    this.f(type, fn, capture);
    console.trace("Added event listener on" + type);
}

即使在这样做之后,然后注释掉导致执行此console.trace的所有代码部分(参见#1),以便在打开/关闭面板时不再打印console.trace,我注意到听众的增加相同在性能图表中。 其他一些因素导致听众增加。 我知道还有其他方法可以添加监听器,但是我不清楚如何拦截所有这些可能性或导致它们以这样的方式登录Chrome的调试器,以便我可以告诉哪些代码负责添加它们。

编辑 : - 根据评论中cowbert的建议,我看了一下这个页面: https//developers.google.com/web/tools/chrome-devtools/console/events

然后我做了以下功能:

function printListenerCount() {
    var eles = document.getElementsByTagName("*");
    var numListeners = 0;
    for (idx in eles) { let listeners = getEventListeners(eles[idx]);
        for(eIdx in listeners)
        {
            numListeners += listeners[eIdx].length;
        }
        console.log("ele", eles[idx], "listeners", getEventListeners(eles[idx]));
    }
    console.log("numListeners", numListeners)
}

我打开/关闭面板多次后执行此功能,但不幸的是“numListeners”数字没有改变。 如果numListeners数字发生了变化,我可以在打开/关闭面板之前/之后对结果进行区分,以发现哪个元素有额外的事件监听器注册到它,但不幸的是numListeners没有改变。

https://developers.google.com/web/tools/chrome-devtools/console/events上还介绍了monitorEvents()API,但函数调用要求您指定要监视的DOM元素。 在这种情况下,我不确定哪个DOM元素有额外的侦听器,所以我不确定monitorEvents()调用将如何真正帮助我。 我可以将它附加到所有DOM元素,类似于我上面编写的printListenerCount函数,但我认为我遇到了类似的问题,我遇到了printListenerCount() - 无论出于何种原因,它都不能解决有问题的听众。

其他说明:这是一个有点复杂的反应(基于预制,技术)的应用程序。 与大多数基于reactjs的应用程序一样,组件可以即时安装/卸载(插入DOM或从DOM中删除)。 我发现这使得跟踪“杂散事件处理程序注册”这样有点棘手。 所以我真正希望的是一些关于如何在诸如此类的大型/复杂项目中追踪“Stray事件处理程序”的一般调试建议。 作为C程序员,我会打开gdb并在所有可能导致性能图中“侦听器”编号增加的内容上设置断点。 我不确定在javascript世界中是否有类似的东西,即使它存在,我也不知道该怎么做。 任何建议将不胜感激!

谢谢大家的评论。 我最终搞清楚了。

从我的OP:

  1. 我的假设是听众是否会得到补充并且从未被束缚似乎是明智的,或者我可以采取更多措施来证实这种怀疑?

事实证明,这个问题的答案是:假设是不明智的。 听众根本没有机会收集垃圾。 这可能比你想象的要花费更多的时间。

以下是我弄清楚的方法:我没有意识到,在录制性能时间线时,可以通过单击“性能”选项卡中的垃圾桶图标(用于启动时间线录制的相同选项卡)强制进行垃圾收集。 通过在UI面板重复关闭/打开后单击此图标,额外的听众完全消失了。 图表现在看起来像这样,逢低是我点击垃圾桶图标的时刻: 使用手动GC的性能时间表

显然,像我在OP中提到的那样,选择标签并等待几分钟根本就没有足够的时间来自行进行垃圾收集; 这需要更多的时间。

当我写OP时,我没有意识到用垃圾桶图标手动收集垃圾的能力......我强烈建议在进行任何疯狂的追逐之前使用它,以寻找可能最初看起来像性能问题的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM