下面给你做一份最清晰、最系统、面试直接用 的完整版对比:
把 BroadcastChannel / MessageChannel / WebSocket / Storage 事件 / postMessage / Worker 这 6 个东西一次性讲透,并做横向对弈。
一、先统一概念
- 通信范围:在哪几个环境之间传消息
- 通信方式:一对一 / 一对多
- 是否跨域
- 是否需要服务端
- 性能与阻塞情况
- 典型用途
二、逐个详细讲解
1. BroadcastChannel
同源多标签、多窗口之间的一对多广播
核心特点
- 同源(域名、协议、端口一致)
- 一对多广播:一个发,所有同频道标签都能收
- 纯前端,无需服务端
- 消息是广播式,无法定向发给某一个标签
- 自己发的消息自己也能收到
基本用法
js
// 所有标签都创建同名频道
const bc = new BroadcastChannel('my-channel')
// 发送
bc.postMessage({ type: 'LOGOUT' })
// 接收
bc.onmessage = (e) => {
console.log(e.data)
}
适用场景
- 多标签同步登录状态
- 一个登出,全部退出
- 多标签同步主题、配置
- 简单跨标签通知
优点
- 干净、标准、API简单
- 不污染 localStorage
缺点
- 必须同源
- 不能定向发送
- 低版本 IE 不支持
2. MessageChannel
点对点、双向管道通信,可做高性能宏任务
核心特点
- 两个端口:port1 ↔ port2 一对一
- 可用于:主线程内部、主线程 ↔ Worker、主线程 ↔ iframe
- 发送的消息会进入宏任务队列
- 比 setTimeout 快,无 4ms 最小延迟
- 可转移端口所有权(Transferable)
基本用法
js
const { port1, port2 } = new MessageChannel()
port1.onmessage = (e) => {}
port2.postMessage('hello')
适用场景
- React 时间切片、任务调度
- 高性能 nextTick
- 安全、隔离的点对点通信
- Worker / iframe 通信
优点
- 极快、稳定
- 不阻塞渲染
- 通信隔离、安全
缺点
- 只能一对一
- API 稍复杂
3. WebSocket
浏览器 ↔ 服务器全双工长连接实时通信
核心特点
- 客户端 ↔ 服务端通信
- 长连接,一次握手,持续双向传输
- 真正实时(聊天、弹幕、推送)
- 可跨域(服务端配置)
- 服务端必须支持 WS / WSS 协议
基本用法
js
const ws = new WebSocket('wss://api.xxx.com/ws')
ws.onopen = () => ws.send('hello')
ws.onmessage = (e) => {}
适用场景
- 聊天
- 实时大屏
- 游戏
- 协同编辑
- 消息推送
优点
- 真正实时
- 全双工
- 省请求,性能高
缺点
- 必须服务端支持
- 断线重连要自己处理
4. Storage 事件
同源跨标签,监听 localStorage 变化
核心特点
- 同源
- 不是主动发消息,而是监听存储变化
- 自己页面不会收到自己的 storage 事件
- 本质是 hack 用法,不是正经通信 API
基本用法
js
window.addEventListener('storage', (e) => {
console.log(e.key, e.oldValue, e.newValue)
})
// 另一个标签修改 localStorage 才会触发
localStorage.setItem('user', 'xxx')
适用场景
- 简单跨标签同步
- 早期无 BroadcastChannel 时的兼容方案
优点
- 兼容性极好
缺点
- 污染 localStorage
- 只能监听,不能主动通信
- 自己收不到自己的修改
- 数据格式麻烦
5. postMessage
通用跨源消息 API(主用于 iframe / 窗口)
核心特点
- 可跨域
- 用于:窗口 ↔ 窗口、iframe ↔ 主页面
- 需指定 targetOrigin,更安全
- 异步,不阻塞
基本用法
js
// 主页面 → iframe
iframe.contentWindow.postMessage(msg, '*')
// iframe 接收
window.onmessage = (e) => {}
适用场景
- 跨域 iframe 通信
- 多窗口通信
优点
- 跨域能力强
- 兼容性好
缺点
- 需处理安全问题
- 不如 MessageChannel 隔离干净
6. Worker + postMessage
主线程 ↔ 子线程通信,后台计算不卡 UI
核心特点
- 主线程与 Worker 子线程之间通信
- Worker 有独立线程,完全不阻塞主线程渲染
- 无 DOM、无 window
- 数据通过结构化克隆传递(可传复杂对象)
基本用法
js
// 主线程
const worker = new Worker('./worker.js')
worker.postMessage(data)
worker.onmessage = (e) => {}
// worker.js
self.onmessage = (e) => {
// 大量计算
self.postMessage(result)
}
适用场景
- 大量计算
- Excel/CSV 解析
- 加解密
- 图像处理
- 大数据遍历
优点
- 真正不卡页面
- 独立线程,计算能力强
缺点
- 无 DOM
- 内存独立,数据拷贝有开销
- 调试稍麻烦
三、终极横向对比表(面试必背)
| BroadcastChannel | MessageChannel | WebSocket | Storage 事件 | postMessage | Worker | |
|---|---|---|---|---|---|---|
| 通信对象 | 同源多标签 | 点对点管道 | 客户端 ↔ 服务端 | 同源多标签 | 窗口/iframe | 主线程 ↔ 子线程 |
| 模式 | 一对多广播 | 一对一 | 全双工 | 被动监听 | 一对一 | 一对一 |
| 跨域 | ❌ | 可 iframe | ✅ | ❌ | ✅ | ❌ |
| 服务端 | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
| 自己收自己 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 阻塞主线程 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌(计算在Worker) |
| 核心定位 | 多标签同步 | 调度/隔离通信 | 实时长连接 | 存储监听 | 跨窗口通信 | 后台 heavy 计算 |
| 代表场景 | 登出同步 | React 切片 | 聊天 | 旧版跨标签 | 跨域iframe | 大数据计算 |
四、一句话选择指南(最强对弈)
- 多标签同源广播 → BroadcastChannel
- 高性能任务调度、时间切片 → MessageChannel
- 客户端与服务端实时通信 → WebSocket
- 监听 localStorage 跨标签 → Storage 事件(不推荐)
- 跨域 iframe / 窗口通信 → postMessage
- 大量计算不卡 UI → Worker + postMessage
五、最经典组合(实际工程必用)
- MessageChannel + Worker:可中断、时间切片计算
- BroadcastChannel:多标签登录同步
- Worker:所有大计算任务
- WebSocket:在线消息、通知
- postMessage:跨域 iframe 通信