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}`); }) })