feng xiaohan

Web Worker

浏览器为 JS 提供的多线程技术,允许在后台运行脚本,避免阻塞主线程(UI 线程),从而提升复杂任务的性能和用户体验。

特点

  • 独立线程:运行在浏览器后台线程,与主线程隔离。两者之间无法直接操作。
  • 通信:主线程和独立线程都可通过 postMessageonmessage 与主线程交换数据。

    注意:数据传递时是被复制的,而不是共享。

  • 兼容性:现代浏览器普遍支持(IE10+)。
  • 错误处理:通过 worker.onerror 捕获 Worker 错误。
  • 资源释放:用 worker.terminate() 手动关闭 Worker。

限制

  • 不能访问 domwindow 对象

    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 的名称。

通信

onmessagepostMessage

加载脚本

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 方法实现原子操作,避免竞争条件。