html5 web worker 本身无线程池机制,需手动封装:预创建固定数量 worker 实例并复用,维护 idle/busy 状态与任务队列,支持优先级调度、并发限制、超时重试及基于 taskid 的结果归集。

HTML5 的 Web Worker 本身不提供线程池或任务队列调度机制,但可以通过 JavaScript 手动封装一个轻量、可控的 Worker 线程池,实现多任务的自动分发、并发控制与结果聚合。核心在于“复用 Worker 实例”+“维护待执行任务队列”+“按需唤醒空闲 Worker”。
设计一个可复用的 Worker 池管理器
避免频繁创建/销毁 Worker(开销大且不可控),应预先初始化固定数量的 Worker 实例,并保持其长期存活。每个 Worker 加载同一份处理脚本(如 worker.js),通过 postMessage 接收任务数据,处理完后回传结果。
- 使用数组存储 Worker 实例,配合状态标记(
busy/idle)跟踪可用性 - Worker 内部需监听
message事件,执行计算逻辑后调用postMessage(result) - 主页面监听每个 Worker 的
message事件,收到结果后将其置为 idle,并触发下一个待办任务
实现带优先级与并发限制的任务队列
任务队列不应是简单 FIFO,而应支持动态调度策略:例如限制最大并发数(如最多 4 个 Worker 同时运行)、允许高优任务插队、自动重试失败任务。
- 用数组 +
shift()/unshift()实现基础队列;高优任务用unshift()插入队首 - 维护
maxConcurrency配置,仅当空闲 Worker 数 ≥ 1 且队列非空时才派发任务 - 每个任务对象建议包含
id、type(如 "encode" / "filter")、data、timeout和retry字段
任务派发与结果归集的闭环通信
Worker 不应直接操作 DOM 或共享内存,所有交互必须通过消息传递。为避免消息混淆,需为每个任务绑定唯一 ID,并在响应中携带该 ID,主页面据此匹配回调。
- 派发任务时:生成唯一
taskId,存入pendingMap = { taskId: resolve },再向空闲 Worker 发送{ taskId, data, type } - Worker 响应时:返回
{ taskId, result, error },主页面查pendingMap触发对应 Promise - 超时或报错时主动 reject,并根据配置决定是否重入队列
实际使用示例(简化版)
假设你有一个图像像素处理任务,希望最多 3 个 Worker 并行执行:
// main.js
const pool = new WorkerPool('./worker.js', { max: 3 });
pool.submit({ type: 'grayscale', data: imageData })
.then(result => console.log('done:', result))
.catch(err => console.error('failed:', err));
对应 worker.js 只需专注计算:
self.onmessage = ({ data }) => {
if (data.type === 'grayscale') {
const result = doGrayscale(data.data);
self.postMessage({ taskId: data.taskId, result });
}
};
不复杂但容易忽略:Worker 中不能访问 window、document,调试需用 self.console.log;主线程与 Worker 之间传递对象会自动结构化克隆(不共享引用)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











