You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未移除Preact中Chrome DevTools网络监听器致重复触发的原因

问题:未移除Chrome DevTools网络监听器导致请求重复大量添加的原因?

我正在开发一款Chrome扩展,使用Preact库。初始状态和useEffect代码如下:

const [requests, setRequests] = useState([]);

useEffect(() => {
    function processRequest(request) {
        // if filter is unset
        if (filter == "") {
            setRequests((requests) => [...requests, request]);
        } else {
            // filter request url using wildcard
            if (request.request.url.includes(filter)) {
                setRequests((requests) => [...requests, request]);
            }
        }
    }


    chrome.devtools.network.onRequestFinished.addListener(processRequest);

    return () => {
        
    }
}, []);

把requests绑定到页面列表后测试发现,一次页面刷新后列表长度达到20000,但实际只有约40个请求,大量请求重复出现,单个请求通常被保存数百次。

意识到未移除事件监听器后,我给useEffect加上了清理逻辑:

return () => {
    chrome.devtools.network.onRequestFinished.removeListener(processRequest);
}

修改后恢复正常。想了解未移除监听器为何会导致监听器被触发数百次?


原因解析

核心原因是重复绑定事件监听器,结合Preact组件的挂载/卸载逻辑和Chrome DevTools的特点,具体逻辑如下:

  • 监听器越绑越多
    组件首次挂载时,useEffect(依赖为空数组,仅首次挂载执行)会给chrome.devtools.network.onRequestFinished绑定一个processRequest函数。但如果组件因为切换DevTools面板、刷新页面等原因卸载后重新挂载,之前绑定的监听器因为没写清理逻辑,会一直留在事件上;新的挂载又会执行useEffect,绑定一个全新的processRequest函数。次数多了,事件上就会绑定成百上千个监听器实例。

  • 单个请求触发所有监听器
    每当一个网络请求完成时,onRequestFinished事件会触发一次,但此时所有绑定的监听器都会执行——每个监听器都会把同一个请求添加到requests数组里,所以单个请求会被重复保存数百次,最终数组长度远大于实际请求数。

  • 清理函数解决重复绑定
    加上removeListener的清理逻辑后,组件卸载时会移除对应的processRequest监听器。这样每次组件重新挂载时,只会存在一个有效的监听器,自然就不会出现重复添加请求的问题了。

额外提醒:你的代码里useEffect依赖数组是空的,但内部用到了filter变量,这会导致filter更新时,监听器里的filter还是旧值(闭包陷阱),建议把filter加入useEffect的依赖数组,同时确保每次依赖变化时先移除旧监听器、再绑定新的,避免过滤逻辑失效。


内容的提问来源于stack exchange,提问作者Max Luan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:50:22