javascript Web Workers是什么_如何实现多线程编程?

15次阅读

Web Workers 是浏览器中唯一真正并行执行 js 的机制,基于独立 JS 环境与消息通信,通过 postMessage/onmessage 传递序列化数据,无法访问 dom、localStorage 等,仅支持同源脚本。

javascript Web Workers是什么_如何实现多线程编程?

Web Workers 不是 javaScript 的线程——它没有共享内存,也不能直接操作 DOM,但它是浏览器里唯一能真正并行执行 JS 代码的机制。

Web Worker 的本质:独立 JS 环境 + 消息通信

每个 Worker 运行在单独的全局上下文(self 代替 window),有自己的事件循环内存和执行主线程和 Worker 之间只能通过 postMessage()onmessage 传递可序列化的数据(或转移 ArrayBuffer)。

  • 不能访问 documentlocalStorageXMLHttpRequest(但可用 fetch
  • console.log 在 Worker 中有效,输出会出现在开发者工具的 “Workers” 标签页下
  • Worker 脚本必须是同源的,且不能是 data:blob: URL(除非用 Blob URL 显式构造)

如何创建并使用 Dedicated Worker

最常用的是专用 Worker(DedicatedWorkerGlobalScope),一对一绑定主线程。

第一步:写一个独立 JS 文件(比如 worker.js):

立即学习Java免费学习笔记(深入)”;

self.onmessage = function(e) {   const data = e.data;   // 假设做 CPU 密集型计算   let result = 0;   for (let i = 0; i < data.n; i++) {     result += i * i;   }   self.postMessage({ result }); };

第二步:在主线程中实例化并通信:

const worker = new Worker('worker.js'); 

worker.onmessage = function(e) { console.log('计算结果:', e.data.result); };

worker.onerror = function(e) { console.error('Worker 报错:', e.message, e.filename, e.lineno); };

worker.postMessage({ n: 1000000 }); // 启动计算

  • 注意路径是相对于 html 页面的,不是相对于当前 JS 文件
  • 如果要用模块化 Worker,需用 new Worker('worker.js', { type: 'module' }),且脚本中用 import
  • 调用 worker.terminate() 可立即销毁 Worker,释放资源;不终止的话,它会一直存活到页面卸载

SharedWorker 和 Service Worker 的关键区别

别混淆三类 Worker:

  • DedicatedWorker:仅被创建它的脚本访问,适合单任务并行(如解析大 json、加密、canvas 预处理)
  • SharedWorker:可被同源多个页面/iframe 共享,用 port.postMessage() 通信,需手动 port.start();已逐渐被弃用,chrome 95+ 默认禁用,不建议新项目使用
  • ServiceWorker:用于拦截网络请求、离线缓存,生命周期由浏览器控制,与页面无直接绑定,不能访问 self.document 也不支持 postMessage 直接传对象(需走 Client API)

如果你只是想把耗时计算搬出主线程避免卡顿,只用 DedicatedWorker 就够了。

常见错误和性能陷阱

实际用 Worker 时,最容易栽在“以为能加速一切”上:

  • 小任务反而更慢:启动 Worker 有开销(约几毫秒),数据序列化/反序列化也有成本;简单运算(如 math.sqrt(123))放 Worker 里纯属负优化
  • 误传大对象:传一个 10MB 的 JSON.stringify 后的字符串,主线程和 Worker 都要复制一份内存;应尽量用 Transferable(如 postMessage(data, [arrayBuffer]))来零拷贝转移二进制数据
  • 忘记错误隔离:Worker 内部报错不会冒泡到主线程,必须监听 worker.onerror 或在 Worker 里加 try/catch + postMessage 主动上报
  • 内存泄漏:Worker 中的闭包、定时器、未注销的事件监听器都会持续占用内存;尤其注意 setInterval 忘记 clearInterval

真正需要 Worker 的场景很具体:长时间运行的数值计算、图像/音视频帧处理、大型数据结构遍历、加密解密、wasm 模块调用——其它时候,优先考虑 requestIdleCallback 或分片(setTimeout 分批)更轻量。

text=ZqhQzanResources