javascript - 当我不再需要这个 `await nextEvent(element, 'mousemove')` 模式时,如何清理它?
问题描述
我有一个 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 })
})
问题是,如果这个组件被卸载,那么添加到 DOM 元素引用的事件处理程序this.elRef.current
将保留在内存中,因为用户将不再与不再在 DOM 中的元素进行交互。
所以while循环会卡住等待下一个事件,这永远不会发生,而且由于while循环还在等待最后一个事件,我相信这会导致实例MyComponent
在内存中泄漏。
或者引擎是否足够聪明来清理它?如果我没有对这些东西的任何可访问引用,并且唯一链接的是 while 循环的范围,它正在等待一些承诺履行,那么引擎会丢弃它吗?或者它会让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
推荐阅读
- mobile - 无法将任何应用程序导入 Appium Studio
- javascript - `npm run build` 时 process.env 不包含 ENV VARS (Ubuntu)
- python - 浮点格式的Python多种格式
- docker - Windows Server 2022 上的 Docker,运行 ELK 堆栈的问题
- javascript - 在 React 中记忆一个函数
- html - Chrome 没有为 Jenkins 上发布的 CSS 文件发送 Session-Cookie
- reactjs - 使用 socket.io 在聊天应用程序中与打字稿作斗争
- pandas - 在 DataFrame 中选择而不输入“INDEX”,而是通过调用用户定义的变量作为现有索引/值
- spring-boot - 我想获取 MongoTemplate 的 findAndModify 返回值作为修改值
- python - plotly px.scatter_3d 标记大小