《红皮书》跨上下文消息

2022-04-15  本文已影响0人  我叫Aliya但是被占用了

官网文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

otherWindow.postMessage(message, targetOrigin, [transfer]);
var popup = window.open("http://www.target.com");
popup.postMessage("ping", "http://www.target.com");
window.addEventListener(
  "message",
  function receiveMessage({ data, origin, source }) {
    if (origin !== "http://www.target.com") return;
    console.log("消息发送者的 window 引用:", source);
    console.log("接收的消息:", data); // pong
  },
  false
);

// http://www.target.com
window.addEventListener(
  "message",
  function receiveMessage({ data, origin, source }) {
    if (origin !== "http://www.origin.com") return;
    source.postMessage("pong", origin);
  },
  false
);

window.addEventListener('message')参数:

对 origin 和 source 的检查有助于避免跨站点脚本攻击

MessageChannel

postMessage 是基于 MessageChannel 实现的,MessageChannel 本身可以用于两个 works 间通讯。

> new MessageChannel()
< MessageChannel {port1: MessagePort, port2: MessagePort}
  port1: MessagePort {onmessage: null, onmessageerror: null, onclose: null, close: f, postMessage: f, start: f}
  port2: MessagePort {onmessage: null, onmessageerror: null, onclose: null, close: f, postMessage: f, start: f}

将 port1 和 port2 分别传给两个 works,works 使用接收的 port 进行消息监听和发送,就可以通过 MessageChannel 进行通信。

BroadcastChannel

基于 name 为一组通讯。两个 works 都使用相同 name 初始化一个 BroadcastChannel,在其实例上监听和发送消息就以彼此通信。

> new BroadcastChannel('test')
< BroadcastChannel {name: 'test', onmessage: null, onmessageerror: null, close: f, postMessage: f}

works 的创建消耗大(时间或空间),基于 BroadcastChannel 发消息时要确保 works 已经初始化完成(已经监听上),以免消息没人处理。

数据的传输

postMessage 会将对象进行结构化克隆(Error 对象、Function 对象或 DOM 节点会抛出错误)后再传输,当对象比较复杂时会比较消耗性能,转为字符串可以缓解这种消耗和兼容老浏览器。

在数据很大时可以使用 可转移对象(transferable objects),比如 postMessage 的 transfer 参数,可以被转移的对象有:

共享数据 SharedArrayBuffer 兼容性有问题

上一篇 下一篇

猜你喜欢

热点阅读