Web Worker
浏览器为 JS 提供的多线程技术,允许在后台运行脚本,避免阻塞主线程(UI 线程),从而提升复杂任务的性能和用户体验。
特点
- 独立线程:运行在浏览器后台线程,与主线程隔离。两者之间无法直接操作。
- 通信:主线程和独立线程都可通过
postMessage和onmessage与主线程交换数据。注意:数据传递时是被复制的,而不是共享。
- 兼容性:现代浏览器普遍支持(IE10+)。
- 错误处理:通过 worker.onerror 捕获 Worker 错误。
- 资源释放:用 worker.terminate() 手动关闭 Worker。
限制
- 不能访问
dom和window对象。Worker 有自己的线程对象
DedicatedWorkerGlobalScope。 - 同源限制:Worker 脚本需与主线程同源。
- 不能使用
alert()和confirm()方法。但是可以使用 AJAX 。
- 无法读取本地文件:不能直接打开
file://协议的资源。
核心原理
浏览器环境本身是多线程的(如网络请求、定时器、渲染引擎等由浏览器管理),当我们创建一个 worker 时,浏览器就会为其分配一个独立的线程与主线程并行执行。该线程由浏览器底层管理,操作系统可能进一步分配 CPU 核心资源。
浏览器的多线程能力基于操作系统(如 Windows 的线程 API、Linux 的 pthread)或引擎(如 V8 的 Isolate 机制)实现。
执行顺序
主线程和 Worker 线程各自运行在独立的线程中,二者的代码执行顺序取决于浏览器的线程调度,我们无法直接控制。通过 postMessage 发送的消息会进入接收线程的消息队列,按事件循环机制处理。
小结
经测试,Web Worker 自身拥有自己的事件循环,主线程和 Worker 中的通信都是在对应触发 postMessage 才会运行接收的,相当于挂载监听器事件;而且两者的微任务和宏任务都是谁先执行完毕谁输出,但是主线程的微任务总是先于 worker 中的微任务,主线程中的宏任务和 worker 的微任务、宏任务执行的顺序就要看浏览器调度了。
基本使用
创建
cosnt myWorker = new Worker(jsUrl, options);
- jsUrl:必须是 js 脚本,并且地址遵守同源策略。
- options:配置对象。可以用于指定 Worker 的名称。
通信
onmessage 和 postMessage。
加载脚本
importScripts。可动态加载多个脚本。
importScripts("script1.js", "script2.js");
错误处理
onerror。
关闭 Worker
- 主线程关闭:
worker.terminate(); - Worker 内部关闭:
self.close();
SharedArrayBuffer
Web Worker 在进行消息传递的时候数据会被复制,而不是共享,这对于大数据量或频繁通信的情况来说可能效率不高。
SharedArrayBuffer 是 JavaScript 中的一个对象,用于在多个线程(如主线程和 Web Workers)之间共享同一块内存区域(固定长度的原始二进制数据缓冲区)。它允许不同线程直接读写同一块内存,从而实现高效的数据共享,避免了通过 postMessage 复制数据的性能开销。
特性
- 共享内存
- 固定长度:创建时需指定缓冲区大小,不可动态调整。
- 类型化视图:通过 TypedArray(如 Int32Array)或 DataView 访问和操作内存。
- 线程安全依赖:需配合 Atomics 方法实现原子操作,避免竞争条件。