MessageChannel
定义: Channel Messaging API允许两个不同的脚本运行在同一个文档的不同浏览器上下文(比如两个 iframe)。
使用MessageChannel()构造函数来创建通讯信道。一旦创建,信道的两个端口即可通过MessageChannel.port1和 MessageChannel.port2属性进行访问(都会返回MessagePort 对象)。创建信道的应用程序使用 port1,在另一端的程序使用 port2 —— 你向 port2 发送信息,然后携带 2 个参数(需要传递的消息,要传递所有权的对象,在这里是 port 自身)调用 window.postMessage方法将端口信息传递到另一个浏览器上下文。
当这些可传递的对象被传递后,他们就从之前所属的上下文中消失了。比如一个 port,一旦被发送,在原本的上下文中就再也不可用了。注意当前仅有 ArrayBuffer和 MessagePort对象可以被发送。
另一个浏览器上下文可以使用 MessagePort.onmessage监听信息,并使用事件的 data 属性获取消息内容。你可以通过 MessagePort.postMessage(en-US)向原来的文档发送应答消息。
当你想要停止通过信道发送消息时,你可以调用来关闭MessagePort.close(en-US)端口。
更多使用这个 API 的资料参见:Using channel messaging 。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>Channel messaging demo</title>
<link rel="stylesheet" href="">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<h1>Channel messaging demo</h1>
<p class="output">My body</p>
<iframe src="page2.html" width='480' height='320'></iframe>
</body>
<script>
var channel = new MessageChannel();
var output = document.querySelector('.output');
var iframe = document.querySelector('iframe');
// Wait for the iframe to load
iframe.addEventListener("load", onLoad);
function onLoad() {
// Listen for messages on port1
channel.port1.onmessage = onMessage;
// Transfer port2 to the iframe
// 第三个参数是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
iframe.contentWindow.postMessage('Hello from the main page!', '*', [channel.port2]);
}
// Handle messages received on port1
function onMessage(e) {
output.innerHTML = e.data;
}
</script>
</html>
page2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>My page title</title>
<link rel="stylesheet" href="">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<p class="output">iFrame body</p>
</body>
<script>
var output = document.querySelector('.output');
window.addEventListener('message', onMessage);
function onMessage(e) {
output.innerHTML = e.data;
// Use the transfered port to post a message back to the main frame
// MessageEvent.ports 表示消息正通过特定通道(数据通道)发送的相关端口 下解释
// 经过试验这里的e是MouseEvent实例。
e.ports[0].postMessage('Message back from the IFrame');
}
</script>
</html>
补充概念
window.postMessage()方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage()方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
从广义上讲,一个窗口可以获得对另一个窗口的引用(比如targetWindow = window.opener),然后在窗口上调用targetWindow.postMessage() 方法分发一个 MessageEvent消息。接收消息的窗口可以根据需要自由处理此事件。传递给 window.postMessage() 的参数(比如 message )将通过消息事件对象暴露给接收消息的窗口。
MessageEvent
MessageEvent 是接口代表一段被目标对象接收的消息。
用来代表下列情况的消息
:
Server-sent events (参见EventSource.onmessage (en-US)).
Web sockets (参见 WebSocket 接口的 onmessage 属性).
Cross-document messaging (参见 Window.postMessage() 和 Window.onmessage).
Channel messaging (参见 MessagePort.postMessage() (en-US) 和MessagePort.onmessage).
Cross-worker/document messaging (参见上面两个入口, 还有 Worker.postMessage(), Worker.onmessage, ServiceWorkerGlobalScope.onmessage (en-US), 等等.)
Broadcast channels (参见 Broadcastchannel.postMessage()) 和 BroadcastChannel.onmessage).
WebRTC data channels (参见 RTCDataChannel.onmessage (en-US)).
通过这个事件触发的动作被定义为一个函数,该函数作为相关message事件 (例如使用前文所列的onmessage 处理器)的事件处理器。
特有
MessageEvent.data (en-US) 只读
返回 DOMString, Blob 或者 ArrayBuffer,包含来自发送者的数据。
MessageEvent.origin (en-US)
返回一个表示消息发送者来源的USVString
MessageEvent.lastEventId (en-US) 只读
DOMString representing a unique ID for the event.
MessageEvent.source (en-US)
MessageEventSource (可以是 WindowProxy, MessagePort, 或 ServiceWorker 对象) 代表消息发送者.
MessageEvent.ports (en-US)
MessagePort对象数组,表示消息正通过特定通道(数据通道)发送的相关端口(适用于通道消息传输或者向一个共享线程(shared work )发送消息时)。