【发布时间】:2018-06-04 20:25:03
【问题描述】:
我有一个相当大的 javascript(带有 react/redux 但没有 jquery)代码库,用于我正在构建的 web 应用程序,我注意到当我在 UI 中反复打开和关闭某个面板时,根据 Chrome 的性能时间表,听众不断增加。
我已经让 chrome 的性能监视器运行了一两分钟,页面处于空闲状态(就在打开/关闭面板之后),希望也许听众会得到垃圾收集,但事实并非如此。在此过程中,我已切换到其他选项卡,也希望在选项卡处于后台时,侦听器会得到垃圾收集,但不幸的是他们没有。
因此,我怀疑有些听众正在注册,但从未取消注册。
这让我想到了两个主要问题:
- 我的假设是听众正在增加而永远不会 unbound 似乎是明智的,或者我可以做更多的事情来确认 这种怀疑?
- 假设我的怀疑是正确的,我怎样才能最好地去
关于追踪事件监听器所在的代码
被添加?我已经尝试过以下方法:
- 查看了负责打开相关面板的代码,查看它在何处添加了任何侦听器,并注释掉这些部分以查看性能图表是否有任何变化。没有变化。
- 像这样覆盖 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 的调试器中,以便我可以知道哪些代码负责添加它们.
编辑: - 在cmets中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,但是函数 call 要求您指定要监视的 DOM 元素。在这种情况下,我不确定哪个 DOM 元素有额外的 听众,所以我不确定 monitorEvents() 调用将如何真正帮助我。我可以将它附加到所有 DOM 元素,类似于我的方式 写了上面的 printListenerCount 函数,但我想我会遇到与 printListenerCount() 类似的问题—— 无论出于何种原因,它都没有考虑到有问题的听众。
其他说明:
这是一个有点复杂的基于 reactjs(preact,技术上)的应用程序。像大多数基于 reactjs 的应用程序一样,组件可以即时安装/卸载(插入到 DOM 中或从 DOM 中删除)。我发现这使得跟踪像这样的“杂散事件处理程序注册”有点棘手。所以我真正希望的是一些关于如何在诸如此类的大型/复杂项目中追踪“杂散事件处理程序”的一般调试建议。作为 C 程序员,我会打开 gdb 并在所有可能导致性能图中“侦听器”数量增加的事物上设置断点。我不确定javascript世界中是否有类似的东西,即使有,我也不确定该怎么做。任何建议将不胜感激!
【问题讨论】:
-
您是否尝试过查看 chrome 中的 monitorEvents() API? developers.google.com/web/tools/chrome-devtools/console/events
-
谢谢,我看了一下,并在我的 OP 中添加了注释。
-
您可以尝试在代码中搜索 addEventListener 的所有实例并在其上放置断点。与原型替换后得到的应该没有太大不同,除非有人在你做之前做了同样的事情......
标签: javascript