-
作用
:MessageChannel作为宏任务
使用广泛,比如react的Scheduler调度
中就使用了MessageChannel,vue某版本的nextTick原理
实现中也是使用了MessageChannel。 上述使用都是为了使用宏任务
。 -
MessageChannel核心
: 利用html5 的postMessage可以跨域传值的特性。1. react中使用 const channel = new MessageChannel() const port = channel.port2 // 每次 port.postMessage() 调用就会添加一个宏任务 // 该宏任务为调用 scheduler.scheduleTask 方法 channel.port1.onmessage = scheduler.scheduleTask const scheduler = { scheduleTask() { // 挑选一个任务并执行 const task = pickTask() const continuousTask = task() // 如果当前任务未完成,则在下个宏任务继续执行 if (continuousTask) { port.postMessage(null) } }, }
-
使用
:const {port1, port2} = new MessageChannel()- 允许我们创建一个新的消息通道,并通过它的两个port1, port2 (
MessagePort
) 属性发送数据。 - port1 与port2 好比打电话时候的两方,它们都可以作为发送方,也都可以作为接受方,取决于使用。
- 发送方页面
用window.postMessage发送数据
(需把另外port对象传递给接受方页面), - 接收方页面
通过window.onMessage 来接受发送方页面发来的信息
- 接收方页面
通过传来的port对象的postMessage方法向发送方页面发送信息
- 发送方页面
通过对应port.onMessage方法接收另外port发来的信息
代码如下:
- 允许我们创建一个新的消息通道,并通过它的两个port1, port2 (
主页面
<!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="" />
</head>
<body>
<p class="output">My body</p>
<iframe src="test.html" width="560" height="320"></iframe>
</body>
<script>
var channel = new MessageChannel();
var output = document.querySelector(".output");
var iframe = document.querySelector("iframe");
iframe.addEventListener("load", onLoad);
function onLoad() {
channel.port1.onmessage = onMessage;
iframe.contentWindow.postMessage(
"Hello from the main page!",
"http://127.0.0.1:5501",
[channel.port2] // 接受方可以通过e.ports[0] 取值
);
}
function onMessage(e) {
output.innerHTML = e.data;
}
</script>
</html>
//test.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="" />
</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;
// e.ports[0] 存储发送方传来的port对象
e.ports[0].postMessage("Message back from the IFrame");
}
</script>
</html>
-
postMessage
:postMessage( data , origin , [transfer] ),接受两个参数
-
data:需要传递的数据,html5规范中该参数可以是JavaScript中的任意基本类型或可复制的对象,但是不是所有浏览器都能完美支持html5,所有还是用JSON将数据序列化比较好。
-
origin : 目标字符串参数,指明目标窗口。其值可以是字符串“*”(表示无限制)或者一个URI。
-
transfer:是一串和message同时传递的Transferable对象。这些对象的所有权将被转移给消息的接收方,发送方不再保有所有权。
-
ps:
-
postMessage是宏任务(优先级不高的宏任务)