MessageChannel用法总结

MessageChannel,顾名思义,通信管道,可以实现两端的通信。

基本用法:

var channel = new MessageChannel();
var port1 = channel.port1;
var port2 = channel.port2;
port1.onmessage = function(event) {
    console.log("port1收到来自port2的数据:" + event.data);
}
port2.onmessage = function(event) {
    console.log("port2收到来自port1的数据:" + event.data);
}

port1.postMessage("发送给port2");
port2.postMessage("发送给port1");

1. 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);
        }
    }
}

2. 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>

3. worker_threads兄弟线程通信

nodejs的MessageChannel虽然与浏览器的,实现方式不同,但是用法相同,都是一个模型。在此列出,阐释这种思想。

//index.js
const {isMainThread, parentPort, threadId, MessageChannel, Worker} = require('worker_threads');
   
if (isMainThread) {
    //__filename是指worker1会走下面的else分支
    //node使用isMainThread来判断走的是主线程还是worker线程
    //这样worker线程的代码可以和主线程写在一个文件中
    const worker1 = createWorker(__filename);
    const worker2 = createWorker('./worker2.js');
    const {port1,port2} = new MessageChannel();
    worker1.postMessage({ port1 }, [port1]);
    worker2.postMessage({ port2 }, [port2]);
} 
else {
    //worker1
    parentPort.once('message', ({port1}) => {
        port1.postMessage('hello');
        port1.on('message', msg => {
            console.log(`thread ${threadId}: receive ${msg}`);
        });
    });
}

function createWorker(filaPath){
    const worker = new Worker(filaPath);
    worker.on('exit', code => { console.log(`main: worker stopped with exit code ${code}`); });
    worker.on('message', msg => {
        console.log(`main: receive ${msg}`);
        worker.postMessage(msg + 1);
    });
    return worker;
}

//worker2.js
const {parentPort,threadId} = require('worker_threads');

parentPort.on('message',({port2}) => {
    port2.postMessage('form worker2');
    port2.on('message',(msg) => {
        console.log(`thread ${threadId}: receive ${msg}`);
    })
})

 

posted @ 2020-05-02 16:28  全玉  阅读(4120)  评论(0编辑  收藏  举报