【JS】postMessage与MessageChannel

前言

postMessageMessageChannel 都是用来实现跨文档跨窗口跨线程(Web Worker)的消息传递机制。

postMessage

可以在 iframe、同源或跨源窗口之间传递数据,也可以用于主线程与 Web Worker 之间的通信。

postMessage 是一种单向的消息传递机制,适用于同源或跨域窗口之间的通信。可以用它来向一个窗口发送消息,而这个窗口通过监听 message 事件来接收消息。通常用于主页面和 iframe 或主线程和 Web Worker 之间的通信。

// 在主线程中创建 Web Worker
const worker = new Worker('worker.js');

// 发送消息到 Worker
worker.postMessage({ type: 'INIT', data: 'Hello!' });

// 在 Worker 中监听消息
self.addEventListener('message', (event) => {
  console.log('监听到的消息:', event.data);
  // 发送响应回主线程
  self.postMessage('你好!');
});

// 在主线程中监听 Worker 的响应
worker.addEventListener('message', (event) => {
  console.log('监听到的消息:', event.data);
});

postMessage实现iframe跨域通信请看本人另一篇文章:postMessage实现iframe跨域通信

MessageChannel

MessageChannel 创建两个 MessagePort 对象,这两个端口可以通过 postMessage 相互通信。它比 postMessage 更灵活,适用于需要复杂双向通信的场景。

// 创建一个 MessageChannel 实例
const channel = new MessageChannel();

// 获取两个端口
const port1 = channel.port1;
const port2 = channel.port2;

// 监听 port1 上的消息
port1.onmessage = (event) => {
  console.log('接收到的消息:', event.data);
};

// 向 port2 发送消息
port2.postMessage('port2发送的消息');

可以在不同的上下文中使用 postMessage 传递 port2 或 port1

file1.js

const channel = new MessageChannel();

// 监听来自 port1 的消息
channel.port1.onmessage = (event) => {
  console.log("接收到的消息:", event.data);
};

// 将 port2 传递给目标文件(iframe 或 Web Worker)
const iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Sending port', '*', [channel.port2]);

// 向 port1 发送一条消息
channel.port1.postMessage("你好,我是file1的消息");

file2.js

// 监听来自主页面的消息
window.addEventListener('message', (event) => {
  // 检查是否收到了 MessageChannel 的 port
  if (event.data === 'Sending port' && event.ports.length > 0) {
    const port2 = event.ports[0];

    // 监听 port2 上的消息
    port2.onmessage = (event) => {
      console.log("监听到的消息:", event.data);

      // 回应 port1 的消息
      port2.postMessage("我是file2的消息");
    };
  }
});

React 调度器 Scheduler 源码也有用到 MessageChannel,根据可用的 API 选择最合适的调度方法。

  • Node.js 环境中,优先使用 setImmediate,它的执行时间更早,并且不会阻止 Node.js 进程退出。
  • MessageChannel 有时可能导致 Node.js 进程延迟退出。在浏览器环境中,比 setTimeout 更精确地控制任务执行时间(更少的时间颗粒度)。例如,setTimeout 可能会有最低延迟限制(如 4 毫秒),而 MessageChannel 可以更快地触发任务。
  • localSetTimeout: 标准的 setTimeout 函数,如果在环境中既没有 setImmediate 也没有 MessageChannel,那么使用 setTimeout 作为最后的回退方案。通常是在非浏览器环境中,比如一些测试环境或非常旧的环境中。

在这里插入图片描述

总结

postMessageMessageChannel
是否支持跨域
通信方式单向通信双向通信
消息数据可以传递基本数据类型和结构化克隆的数据(如对象、数组、文件等),但不能直接传递上下文(如函数)不仅可以传递数据,还可以通过 postMessage 传递 MessagePort,从而创建多个通信通道
优势简单快捷适用于较复杂的双向通信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田本初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值