什么是Web Workersjavascript_如何实现多线程【教程】

Web Workers 是通过独立执行上下文实现并发的机制,非真正多线程;必须用 new Worker() 加载同源 JS 文件或 Blob URL;通信仅靠 postMessage(),数据序列化传递,支持 transferable 零拷贝;无 DOM、window 等全局对象;console 输出在 Workers 面板;需显式 terminate() 销毁。

Web Workers 不是 JavaScript 的“多线程”(JS 主线程本身仍是单线程),而是通过独立的执行上下文实现真正的并发任务处理——它让你能把耗时计算、数据解析、加密等重活从主线程剥离,避免阻塞 UI。

Web Worker 必须用 new Worker() 实例化,且脚本路径受同源限制

Worker 脚本不能内联(不支持 new Worker("function() { ... }")),必须是一个独立的 .js 文件或使用 Blob URL 动态生成:

  • 直接加载: const worker = new Worker("./math-worker.js");
  • 动态脚本(绕过文件限制):需构造 Blob + URL.createObjectURL(),否则会报 DOMException: Failed to construct 'Worker': Script at ... violates the following Content Security Policy directive
  • 路径必须同源;跨域会触发 NetworkError,连 onerror 都可能不触发,只在控制台报错

postMessage() 是唯一通信方式,主线程和 Worker 之间无法共享变量或 DOM

Worker 运行在完全隔离的全局环境(没有 windowdocumentlocalStorage),所有数据传递靠序列化(结构化克隆算法),注意:

  • 函数、undefinedSymbol、循环引用对象会被静默丢弃
  • 传递大数组或

    ArrayBuffer 时,用 transferable 参数可零拷贝移动内存(如 worker.postMessage(arr, [arr.buffer])),否则默认深拷贝,性能暴跌
  • 主线程监听用 worker.onmessage,Worker 内部用 self.onmessage(不能用 this,因为 this !== self

Worker 中不能调用 console.log?其实是能的,但输出位置不在页面控制台

Worker 的 console 输出会出现在「Application」→「Service Workers」或「Workers」面板下(Chrome / Edge),不是主页面的 Console 标签页。调试时容易误判为没执行:

  • self.console.log() 或直接 console.log() 都可以,但别指望在主控制台看到
  • 想断点调试:在 Worker 脚本里加 debugger,然后打开 DevTools → 「Sources」→ 「Workers」侧边栏,选中对应 worker 即可
  • 出错时 onerror 回调中的 event.filenameevent.lineno 指向 Worker 脚本位置,不是调用处

真正容易被忽略的是生命周期管理:Worker 实例不会自动销毁,worker.terminate() 必须显式调用,否则长期驻留内存;而一旦终止,再发 postMessage 就会静默失败——既不报错,也不触发 onerror