【问题标题】:JavaScript event listener memory leakJavaScript 事件监听器内存泄漏
【发布时间】:2024-01-29 17:00:01
【问题描述】:

我正在使用 React、Redux 和 Three.js 开发一个 WebGL 应用程序。我的应用程序使用鼠标移动和点击作为输入。现在由于某种原因,每当我单击或移动鼠标时,我的应用程序都会变得越来越慢。如下面的性能配置文件所示,似乎存在某种内存泄漏,导致事件侦听器使用的内存不断增长。

据我了解,屏幕截图中的黄线显示事件侦听器的内存使用量不断增长。

但是这条黄线到底代表什么?它是事件侦听器使用的内存量吗?还是注册听众的数量?还是已注册/未处理的事件数?

过去有没有人遇到过类似的问题,也许找到了解决方案?

我的应用程序/原型的完整代码可以在this repository 中找到。不幸的是,我还不能找出问题的原因或用简单的代码 sn-p 重现它。

【问题讨论】:

  • 听众好像很多,实际应该有多少?
  • 蓝线是内存占用。黄线是您页面中的听众数量。您是否继续向组件添加事件回调而不删除旧的?
  • 应该只有一个用于鼠标点击的事件监听器和一个用于移动的事件监听器。因此,出于某种原因,似乎在每次单击/鼠标移动时都会添加一个额外的事件侦听器。但这怎么可能呢?我的事件回调中没有.addEventListener() 之类的东西。我只是将事件处理函数作为道具传递给我的组件,通常的 React 方式......
  • 我在类似的 Webgl 应用程序中遇到了同样的问题。没有三个.js。

标签: javascript reactjs google-chrome


【解决方案1】:

这实际上可能只是开发人员的问题。如果你用NODE_ENV=production构建react项目,这个问题可能不会持续。

这似乎与 react 上的一个未解决问题有关:https://github.com/facebook/react/issues/12141

【讨论】:

    【解决方案2】:

    我快速浏览了您的代码,我猜您将 => 函数传递给将函数添加为侦听器的东西,然后尝试将其删除(例如here) .您不能删除 => 侦听器,因为每次调用渲染方法时都会创建一个新函数(因此在某处调用 .removeEventListener(myArrowFunction) 将尝试将该函数与已添加的函数匹配,但是 它们不相等

    无论如何,不​​要将箭头函数用作侦听器。

    编辑:嗯,是的,使用箭头函数,但声明为实例方法。或存储为常量。不像闭包。

    【讨论】:

    • 但这不是在 React/Redux 中处理事件的常用方式吗? (如this example)。据我所知,React 处理事件/事件侦听器注册的方式与普通 JS 不同,因此在 React 中,onClick 属性的工作方式与.addEventListener() 不同。因此,为什么不断添加事件侦听器更加令人困惑。
    • React 可以,但也许 ThreeJS 不可以?这只是帮助您深入研究问题的指针:-)
    • 而且可能是指向正确方向的指针 :-) 这确实可能是 ThreeJS 问题,因为一旦我从脚本中删除 ThreeJS 渲染器,错误就不会发生。还是很奇怪,特别是因为 onClick 处理程序不会直接影响 ThreeJS 渲染器或它的 DOM 元素...