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

WebWorker运行一段时间致Chrome标签页崩溃问题排查与解决

问题分析与修复方案

问题现象

在React组件中使用WebWorker每隔1秒调用API获取数据,初期运行正常,一段时间后Chrome标签页冻结无响应,WebWorker仍在后台运行,且CPU占用率极高。

原因分析

  1. WebWorker未被正确销毁:React组件的useEffect清理函数仅设置加载状态,未调用worker.terminate()。组件卸载后WebWorker会持续在后台运行,若组件多次挂载(如路由切换),会创建多个独立的WebWorker实例,每个都在每秒发起请求,CPU占用持续累积。
  2. 定时逻辑导致请求堆积:当前用递归setTimeout实现的定时任务,调用getData后立刻设置下一个1秒定时器,完全不等待API请求完成。若API响应耗时超过1秒,会导致多个请求并发执行,随着时间推移并发请求数量持续增加,加剧CPU和网络负载。
  3. 错误处理不完整:try/catch无法捕获fetch的HTTP错误(如4xx/5xx状态码),这类错误会被忽略,可能导致无意义的重复请求,进一步消耗资源。

修复方案

1. 组件卸载时终止WebWorker

在useEffect的清理函数中添加worker.terminate(),确保组件销毁时同步终止WebWorker,避免后台残留实例:

useEffect(() => {
  setIsLoading(true)
  const worker = new Worker('worker.js')
  const token = localStorage.getItem(Constants.TOKEN);
  const backendServer = window['backendServer'];

  worker.postMessage({ _subservice, token, backendServer })

  worker.onmessage = (event) => {
    setData(event.data)
    setIsLoading(false)
  }
  worker.onmessageerror = (event) => {
    console.log('msg errrrrrror', event)
  }
  worker.onerror = (event) => {
    console.error('error received from worker:', event);
  }

  return () => {
    setIsLoading(false)
    worker.terminate() // 销毁WebWorker
  };
}, []);

2. 修改WebWorker定时逻辑,等待请求完成后再启动下一次任务

将递归定时器改为在API请求完成(成功/失败)后再设置下一次定时,避免请求堆积:

onmessage = (event) => {
    const { _subservice, token, backendServer } = event.data
    const getData = async () => {
        const body = {
            subservice: _subservice,
            command: 'info'
        };
        try {
            const response = await fetch(backendServer, {
                method: 'POST',
                headers: {
                    'Authorization': `Token ${token}`,
                    'Content-Type': 'application/json' // 指定请求格式,避免服务器解析异常
                },
                body: JSON.stringify({
                    'data': body
                })
            });
            // 处理HTTP错误状态码
            if (!response.ok) {
                throw new Error(`请求失败:${response.status}`);
            }
            const data = await response.json();
            postMessage(data.response);
        } catch (error) {
            console.error('获取数据失败:', error);
        } finally {
            // 请求完成后,1秒后发起下一次请求
            setTimeout(nextInterval, 1000);
        }
    };
    const nextInterval = () => {
        getData();
    }
    // 启动首次请求
    nextInterval();
}

3. 防止重复启动定时循环(可选)

若担心WebWorker收到多次message导致重复启动定时任务,可添加运行状态标志:

let isTaskRunning = false;
onmessage = (event) => {
    if (isTaskRunning) return; // 已有任务在运行,直接返回
    isTaskRunning = true;
    
    const { _subservice, token, backendServer } = event.data
    const getData = async () => {
        // 同上逻辑...
    };
    const nextInterval = () => {
        getData();
    }
    nextInterval();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:07:02