《红皮书》跨上下文消息
2022-04-15 本文已影响0人
我叫Aliya但是被占用了
官网文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
otherWindow.postMessage(message, targetOrigin, [transfer]);
- otherWindow:其他窗口的引用,如 iframe 的 contentWindow、window.opener 等
- message:会被结构化克隆算法序列化
- targetOrigin:目标窗口的 Origin 或 *
- transfer:是一串和 message 同时传递的 Transferable 对象(ArrayBuffer、MessagePort 和 ImageBitmap)(大对象移交指针?)
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')
参数:
- data 接受到的数据
- origin 发送者 origin
- source 发送者的 window 引用
对 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 参数,可以被转移的对象有:
- ❑ ArrayBuffer ❑ MessagePort ❑ ImageBitmap ❑ OffscreenCanvas
共享数据 SharedArrayBuffer 兼容性有问题