Web Workers定义回顾与使用问题:如何用Worker实现批量请求处理
问题分析
现有代码存在3个核心问题导致功能无法正常运行:
- 调用
worker.postMessage()后立即执行worker.terminate(),Worker线程刚收到任务还未完成请求、返回结果就被销毁,因此永远触发不了onmessage回调 - 循环同步创建10个Worker实例,资源开销大,且所有请求异步执行无顺序控制,容易触发服务端请求限流
- Redux更新依赖外部
CDs变量,该变量是useSelector返回的闭包快照,多次回调执行时会出现状态覆盖,最终结果缺失
修复实现
1. 主线程代码改写
用Promise封装Worker的单次任务执行逻辑,保证任务完成后再销毁Worker,同时优化Redux更新逻辑:
const DivideNum = 10; const cuttedIds = [ [{id: "shVwksbhj78qr_bsj", name: "React"}], [{id: "jhjked89djYTeik_h", name: "React Native"}], // 其余数组项 ]; const dis = useDispatch(); // 封装单个Worker任务为Promise const runWorkerTask = (taskData) => { return new Promise((resolve, reject) => { const worker = new Worker("worker.js"); worker.postMessage(taskData); worker.onmessage = (e) => { worker.terminate(); // 任务完成后再销毁Worker resolve(e.data); }; worker.onerror = (error) => { worker.terminate(); reject(error); }; }); }; const setWorkers = async () => { try { // 并发执行所有Worker任务,请求量过大时可替换为限流并发逻辑 const taskPromiseList = cuttedIds.slice(0, DivideNum).map(item => runWorkerTask(item)); const resultList = await Promise.all(taskPromiseList); // 函数式更新Redux,拿到最新的列表状态避免覆盖 dis(updateBooks(prevBooks => [...prevBooks, ...resultList.flat()])); } catch (err) { console.error('任务执行失败:', err); } };
2. worker.js 实现示例
Worker内可正常使用fetch/XMLHttpRequest发起请求,代码如下:
// worker.js 内部代码 self.onmessage = async (e) => { const taskList = e.data; const result = []; try { for (const item of taskList) { // 替换为实际的请求逻辑 const res = await fetch(`你的接口地址/${item.id}`); const data = await res.json(); result.push(data); } self.postMessage(result); } catch (err) { self.postMessage({ error: err.message }); } };
额外优化建议
- 若请求总量大,可固定创建2-4个Worker实例复用,避免频繁创建销毁线程的性能开销
- 单批请求量超过接口限流阈值时,可将
Promise.all替换为串行/限流并发逻辑,避免请求被拦截 - 若需要实时更新状态,可在每个Worker任务resolve后单独触发dispatch,依然要使用函数式更新写法保证状态正确
内容的提问来源于stack exchange,提问作者MIZ3587
相关产品推荐
相关产品推荐

