MessageChannel和BroadcastChannel

常见的 macro task setTimeoutMessageChannelpostMessagesetImmediate。而常见的 micro taskMutationObseverPromise.then

 

MessageChannel

Channel Messaging API的MessageChannel 接口允许我们创建一个新的消息通道,并通过它的两个MessagePort 属性发送数据。

Note: 此特性在 Web Worker 中可用

 iframe通信

//主页面
<iframe id="iframe1" src="./iframe1.html"></iframe>
<iframe id="iframe2" src="./iframe2.html"></iframe>
<script>
    window.onload = function(){
        var {port1,port2} = new MessageChannel();
        var iframe1 = document.getElementById('iframe1');
        iframe1.contentWindow.postMessage('main','*',[port1]);
        var iframe2 = document.getElementById('iframe2');
        iframe2.contentWindow.postMessage('main','*',[port2]);
    }
</script>

//iframe1
<div id="message"></div>
<script>
    window.addEventListener('message',function(event){
        console.log(event);
        let messageDom = document.getElementById('message');
        messageDom.innerHTML = "收到"  + event.origin + "消息:" + event.data;

        let port = event.ports[0];
        port.onmessage = function(e){
            messageDom.innerHTML += '<br/>收到' + e.origin + '消息: ' + e.data;
        }
        port.postMessage('from iframe1');
  }, false);
</script>

//iframe2
<div id="message"></div>
<script>
    window.addEventListener('message',function(event){
        console.log(event);
        let messageDom = document.getElementById('message');
        messageDom.innerHTML = "收到"  + event.origin + "消息:" + event.data;

        let port = event.ports[0];
        port.onmessage = function(e){
            messageDom.innerHTML += '<br/>收到' + e.origin + '消息: ' + e.data;
        }
        port.postMessage('from iframe2');
    }, false);
</script>

Web Worker通信

let worker1 = new Worker('./worker1.js');
let worker2 = new Worker('./worker2.js');
let ms = new MessageChannel();

// 把 port1 分配给 worker1
worker1.postMessage('main', [ms.port1]);
// 把 port2 分配给 worker2
worker2.postMessage('main', [ms.port2]);

//worker1.js
self.onmessage = function(e) {
    console.log('worker1', e.ports);
    if (e.data === 'main') {
        const port = e.ports[0];
        port.postMessage(`worker1: Hi! I'm worker1`);
        port.onmessage = function(ev){
            console.log('reveice: ',ev.data,ev.origin);
        }
    }       
}

//worker2.js
self.onmessage = function(e) {
    if (e.data === 'main') {
        const port = e.ports[0];
        port.onmessage = function(e) {
            console.log('receive: ', e.data);
            port.postMessage('worker2: ' + e.data);
        }
    }
}

BroadcastChannel

Broadcast Channel API 可以实现同  下浏览器不同窗口,Tab页,frame或者 iframe 下的 浏览器上下文 (通常是同一个网站下不同的页面)之间的简单通讯。

Note: 此特性在 Web Worker 中可用

广播频道会被命名和绑定到指定的源。

通过创建一个监听某个频道下的 BroadcastChannel 对象,你可以接收发送给该频道的所有消息。一个有意思的点是,你不需要再维护需要通信的 iframe 或 worker 的索引。它们可以通过构造 BroadcastChannel 来简单地“订阅”特定频道,并在它们之间进行全双工(双向)通信。

const bc1= new BroadcastChannel('channelA')
const bc2= new BroadcastChannel('channelB')
 
bc1.onmessage = (ev) => {
    console.log(ev.data);
}
 
setTimeout(() => {
    bc2.postMessage({message: 'hello'})
}, 1000)

setTimeout(() => {
    bc1.close();
    bc2.close();
}, 2000)
在 Android 中,MessageChannel 是一种通过 WebView 实现 JavaScript Native 之间双向通信的机制。使用 MessageChannel,我们可以在 JavaScript Native 之间传递消息数据。MessageChannel 可以传递基本数据类型(如字符串、整数、布尔值等),也可以传递对象。 使用 MessageChannel 传递对象的步骤如下: 1. 在 Native 中创建一个 MessageChannel,并将其注册到 WebView 中: ```java // 创建 MessageChannel MessageChannel channel = new MessageChannel(); // 将 channel.port1 注入到 WebView 中 webView.addJavascriptInterface(new MyJavaScriptInterface(channel.port1), "MyJavaScriptInterface"); ``` 在这个例子中,我们创建了一个 MessageChannel,并将其注册到 WebView 中。我们也创建了一个名为 "MyJavaScriptInterface" 的 JavaScript 接口,并将 channel.port1 注入到该接口中。这样,JavaScript 就可以通过 "MyJavaScriptInterface" 对象来访问 channel.port1。 2. 在 JavaScript 中创建一个 MessageChannel,并将其与 Native 中的 channel.port2 相关联: ```javascript // 创建 MessageChannel var channel = new MessageChannel(); // 发送 channel.port2 到 Native 端 window.MyJavaScriptInterface.postMessage(channel.port2, [channel.port2]); ``` 在这个例子中,我们创建了一个 MessageChannel,并将其与 Native 中的 channel.port2 相关联。我们也使用 window.MyJavaScriptInterface.postMessage() 方法将 channel.port2 发送到 Native 端。 3. 在 Native 中接收 JavaScript 发送的数据: ```java class MyJavaScriptInterface { private MessagePort port; public MyJavaScriptInterface(MessagePort port) { this.port = port; this.port.setWebContentsDebuggingEnabled(true); this.port.setDelegate(new MessagePort.Delegate() { @Override public void onMessagePortMessage(MessagePort messagePort, MessagePort.MessageEvent messageEvent) { // 处理 JavaScript 发送的数据 Object data = messageEvent.getData(); // ... } }); } } ``` 在这个例子中,我们创建了一个名为 MyJavaScriptInterface 的 Java 类,并在构造函数中设置了 MessagePort 的回调函数。当 JavaScript 发送数据到 Native 端时,该回调函数会被触发,并且我们可以在该函数中处理 JavaScript 发送的数据。 需要注意的是,由于 MessageChannel 是跨线程的,因此需要使用 Handler 或者 AsyncTask 等机制来确保数据的同步安全性。此外,在传递对象时,需要确保对象是可序列化的。如果对象无法序列化,则需要将其转换为可序列化的格式(如 JSON 对象等),然后再传递。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值