javascript - 当我不再需要这个 `await nextEvent(element, ' mousemove')` 模式时,如何清理它?

标签 javascript reactjs typescript memory-leaks code-cleanup

我有一个 React 组件,其中包含如下代码:

class MyComponent extends React.Component {
    // ...

    trackStats = false

    componentDidMount() {
        this.monitorActivity()
    }

    componentWillUnmount() {
        this.trackStats = false
    }

    async monitorActivity() {
        this.trackStats = true

        while (this.trackStats && this.elRef.current) {
            // elRef is a React ref to a DOM element rendered in render()
            await Promise.race([
                nextEvent(this.elRef.current, 'keydown'),
                nextEvent(this.elRef.current, 'click'),
                nextEvent(this.elRef.current, 'mousemove'),
                nextEvent(this.elRef.current, 'pointermove'),
            ])

            this.logUserActivity()
        }
    }

    logUserActivity() {
        // ...
    }

    render() { /* ... */ }
}

const nextEvent = (target, eventName) => new Promise(resolve => {
    target.addEventListener(eventName, resolve, { once: true })
})

问题是,如果卸载此组件,则添加到 this.elRef.current 引用的 DOM 元素上的事件处理程序将保留在内存中,因为用户将不再与不再位于 DOM 中的元素进行交互。

因此 while 循环将卡住等待下一个事件,这永远不会发生,并且因为 while 循环仍在等待最后一个事件,我相信这将导致 MyComponent 的实例> 内存泄漏。

或者引擎是否足够聪明来清理这个问题?如果我没有对任何这些东西的可访问引用,并且唯一链接的是 while 循环的作用域,它正在等待某些 promise 的履行,那么引擎会丢弃它吗?或者它会让 while 循环作用域继续运行,等待 Promises?

如果 while 循环仍然存在(我猜是这样),我应该如何清理它?

最佳答案

啊,有趣的用例!这似乎是 AbortController 的一个很好的用例。 :

function nextEvent(target, type, abortSignal) {
  return new Promise(resolve => {
    target.addEventListener(type, resolve, { once: true });
    abortSignal.addEventListener("abort", () =>
      target.removeEventListener(type, resolve)
    );
  });
}

const abortController = new AbortController();

const event = await Promise.race([
  nextEvent(someButton, "click", abortController.signal),
  nextEvent(someButton, "keydown", abortController.signal)
]);
// Clean up all remaining event handlers
abortController.abort();
// Continue as normal

关于javascript - 当我不再需要这个 `await nextEvent(element, ' mousemove')` 模式时,如何清理它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54033057/

相关文章:

jquery - TS2339 : Property 'selectpicker' does not exist on type 'JQuery<HTMLElement>'

javascript - 或者选择器中的运算符

javascript - jQuery 切换 : Close all open li when another one is clicked

javascript - 在 Mozilla Persona 中登录后如何更新 loggedInUser

javascript - jQuery Flot 跳过 x 轴值

javascript - 动态表单为第一个和第二个输入返回相同的值

reactjs - 在 react 中提交表单后重定向到网站

javascript - react-native app 已经启动,现在添加导航

javascript - 非主文件的输入

javascript - 如何从解析平台检索对象并使用 Typescript 显示它们?