web worker
title: Web Worker 通信深度解析(底层原理版)
date: 2026-01-30
category: “JavaScript / 浏览器内核”
Web Worker 核心笔记
1. Web Worker 角色定位
- 多线程模型:JavaScript 在后台开启独立线程,不占用主线程(UI 线程)。
- 物理隔离:拥有独立的 Event Loop、独立内存、独立的全局对象(self/WorkerGlobalScope)。
- 局限性:无法访问 DOM、
localStorage或window对象。
2. postMessage 通信底层流程(核心)
跨线程通信并非“瞬间移动”,而是遵循 “打包 -> 投递 -> 排队 -> 执行” 的逻辑:
- 打包(发送方):
执行postMessage(data),浏览器利用“结构化克隆算法”对数据进行深拷贝。 - 入队(接收方):
浏览器内核将“消息数据”与“处理逻辑”封装成一个 Message Task(宏任务),直接塞进接收方线程的 宏任务队列。 - 触发执行(接收方):
当接收方的事件循环(Event Loop)轮询到该任务时:- 取出任务:任务出队。
- 即刻执行:直接触发
onmessage回调函数。 - 注入参数:将打包的数据作为
event.data传入回调。
3. 核心知识点校准 ⚠️
- 单一任务化:
postMessage产生的任务本身就包含了回调逻辑。任务出队时,直接执行回调,不需要二次排队。 - 异步性:发送消息是同步的调用,但接收消息永远是异步的(必须等当前执行栈清空、等 Event Loop 调度)。
- 顺序性:同一个线程发出的多个
postMessage任务,会严格按照发送顺序进入目标队列,并按顺序执行。
4. 事件循环模型对比
| 特性 | 主线程 DOM 事件 (click) | Worker 消息事件 (postMessage) |
|---|---|---|
| 任务类型 | 宏任务 (Macrotask) | 宏任务 (Macrotask) |
| 触发点 | 外部触发(用户/硬件) | 内部触发(JS 代码指令) |
| 调度流程 | 浏览器捕获 -> 任务入队 -> 循环执行 | 代码调用 -> 跨线程入队 -> 循环执行 |
5. 老师总结的简记口诀
发消息,即下单;
传数据,进队列;
轮到它,即执行;
不插队,不重复。
6. 进阶提示
- 大数据传递:若数据量极大(如 100MB 数组),克隆会产生性能损耗,此时应考虑使用 Transferable Objects(如
ArrayBuffer)来转移所有权而非克隆。
这部分差异极其关键,它能帮你彻底分清“异步”的两种不同来源。我们可以把这个差异定义为 “被动监听”与“主动投递” 的区别。
这是为你准备的补充笔记,可以直接追加到之前的 .md 文件中:
7. 深度进阶:DOM 事件与 postMessage 的本质差异
虽然两者最终都表现为“宏任务”,但它们的生命周期和入队机制完全不同:
A. DOM 事件:被动监听机制 (Reactive)
- 逻辑:
addEventListener只是在浏览器内核注册了一个“预案”,此时任务队列是空的。 - 入队时机:只有当外部事件(如用户点击、网络包到达)真实发生时,浏览器内核才会临时产生一个任务扔进队列。
- 特点:任务的产生取决于外部环境,具有不可预测性。
B. postMessage:主动投递机制 (Proactive)
- 逻辑:
postMessage是一种显式的“跨线程任务派遣”。 - 入队时机:当你执行代码的那一刻,任务就已经产生并进入对方队列了。它不等待外部触发,而是 JS 执行流的直接延伸。
- 特点:任务的产生取决于内部代码逻辑,具有高度的可控性。
差异对比表
| 维度 | DOM 事件 (如 Click) | Web Worker (postMessage) |
|---|---|---|
| 任务发起者 | 浏览器外部(用户/硬件) | JavaScript 代码内部 |
| 队列状态 | 触发前队列为空,仅有监听器 | 调用即入队,任务立即排队 |
| 数据来源 | 浏览器生成的 Event 对象 |
JS 显式传递并克隆的 data |
| 本质比喻 | 陷阱:踩到(点击)才会触发 | 快递:寄出(调用)即在路上 |
8. 底层总结(Archive 核心)
结论:
postMessage并不是在“等待某个事件发生”,它本身就是创造任务的动作。
这种差异决定了:
- DOM 事件是为了响应(Response);
- Web Worker 通信是为了协作(Collaboration)。
postMessage 的本质,就是跨越线程屏障,直接把“执行回调”这个任务,亲手塞进对方的宏任务队列里。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 YianNotes!

