MessageChannel 消息通道


一、初識 MessageChannel 對象

通過構造函數 MessageChannel() 可以創建一個消息通道,實例化的對象會繼承兩個屬性:port1port2

port1 和 port2 都是 MessagePort 對象,在這里是只讀的,無法對其進行字面量賦值

不過可以給 port 添加屬性

上圖還體現了 MessagePort 對象具有 onmessageonmessageerror 兩個屬性

這是兩個回調方法,使用 MessagePort.postMessage 方法發送消息的時候,就會觸發另一個端口的 onmessage

 

消息通道就像是一條左右貫通的管道,左右兩個端口就是 port1 和 port2

這兩個端口可以相互發送消息,port1 發送的消息可以在 port2 接收到,反之亦然

 

 

二、多個 Web Worker 之間通信

MessageChannel 可以結合 Web Worker 實現多線程通信

// main.js
 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]); worker2.onmessage = function(event) { console.log(event.data); }

這里的 postMessage() 可以接收兩個參數:message、transferList

message 消息內容,可以是任意基礎數據類型
transferList 由被傳輸對象組成的數組,這些對象的所有權會轉移給調用 postMessage 的對象

 

 

 

所以上面的代碼,就是把消息通道的 port1 分配給了 worker1,把 port2 分配給 worker2

也就是用消息通道,將兩個 worker 給連接起來

// worker1.js onmessage = function(e) { if (e.data === 'main') { const port = e.ports[0]; port.postMessage('Hi! I'm worker1'); } }
// worker2.js
onmessage = function(e) { if (e.data === 'main') { const port = e.ports[0]; port.onmessage = function(e) { postMessage(e.data); } } }

代碼運行的時候,worker1 中通過 port1 發送消息,然后 worker2 就能從 port2 中接收到消息

 

三、深拷貝

大部分需要深拷貝的場景,都可以使用以下代碼:

JSON.parse(JSON.stringify(object))

但這種辦法會忽略 undefined、function、symbol循環引用的對象

而通過 postMessage() 方法傳輸的 message 參數是深拷貝的

所以可以借用 MessageChannel 實現深拷貝:

// 深拷貝函數
function deepClone(val) { return new Promise(resolve => { const { port1, port2 } = new MessageChannel() port2.onmessage = e => resolve(e.data) port1.postMessage(val) }) } // 定義一個包含 undefined 的對象
let obj = { a: 'wise', b: undefined, c: { d: 'wrong' } } // 循環引用
obj.c.e = obj.c // 注意該方法是異步的
async function test() { const clone = await deepClone(obj) console.log(clone) } test()

但這個深拷貝只能解決 undefined循環引用對象的問題,對於 Symbolfunction 依然束手無策

 

 

參考資料:

《HTML5 postMessage iframe跨域web通信簡介》

《MessageChannel是什么,怎么使用?》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM