iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0

BroadcastChannel 是 HTML 規範中用來讓多個線程互相溝通的方式,不像前兩天介紹的 MessageChannel 只能做到兩者之間的通訊,BroadcastChannel 以一對多廣播的方式傳送消息。

如下圖所示,BroadcastChannel 擔任中介者的角色將訊息傳遞給 window, tab 或是 iframe
https://ithelp.ithome.com.tw/upload/images/20230925/20162687XgXUZfnrxz.png

創建 BroadcastChannel

一開始需要為創建的 BroadcastChannel 取名,這裡的名稱是 worker_channel,之後如果要與其他頻道進行通信的話,也要命名成同樣的名稱

const channel = new BroadcastChannel("worker_channel");

發送訊息

一樣用 postMessage 的方式將訊息傳遞出去,背後用到的也一樣是前幾天所提到的 structuredClone 算法先將訊息進行深複製。但 channel.postMessage 本身並沒有第二個 transfer 參數,所以數據的傳遞都是複製過的

channel.postMessage("This is a test message.");

關閉訊息

BroadcastChannel 不會再使用到的時候,需要手動關閉它避免資源消耗

channel.close();

限制同源傳遞 (same-origin)

BroadcastChannel 的溝通對象之間只允許同源頁面,因此不需要像前兩天介紹到的 MessagePort,接收訊息前需要先檢驗是否從可信任網域來的

範例

接著讓我們看 BroadcastChannel 要怎麼與 web worker 做搭配,達到各種 worker 間的訊息溝通吧

Demo 連結

https://ithelp.ithome.com.tw/upload/images/20230925/20162687ecxfshxfe9.png

範例中利用 BroadcastChannel 傳遞資料到 worker 中進行加減法運算,加法計算會將 [5, 3] 的值傳到 plus-worker 中,而減法計算會將 [5, 3] 的值傳到另一個 minus-worker,以下是程式碼的說明:

一開始時創建兩個 BroadcastChannel,分別用做傳遞給 plus-workerminus-worker 的通訊管道

const plusWorkerChannel = new BroadcastChannel("plus_worker_channel");
const minusWorkerChannel = new BroadcastChannel("minus_worker_channel");

接著在按下計算按鈕後,取得輸入框的數值,並分別傳遞到兩個 worker

// 按下按鈕後,將數值分別傳到 worker 計算
document.querySelector('button').onclick = () => {
  // 取得加法輸入框 (ex. [5, 3])
  const plusValues = getValues('plus');
  plusWorkerChannel.postMessage(plusValues);

  // 取得減法輸入框數值 (ex. [5, 3])
  const minusValues = getValues('minus');
  minusWorkerChannel.postMessage(minusValues);
};

worker 接收到訊息後,分別進行計算,再將結果送回主頁面
plus-worker.js

const channel = new BroadcastChannel("plus_worker_channel");

channel.onmessage = (e) => {
  console.log("plus-worker 接收到的資料", e.data);

  const [value1, value2] = e.data;
  channel.postMessage(value1 + value2);
};

minus-worker.js

const channel = new BroadcastChannel("minus_worker_channel");

channel.onmessage = (e) => {
  console.log("minus-worker 接收到的資料", e.data);

  const [value1, value2] = e.data;
  channel.postMessage(value1 - value2);
};

最後主頁面從兩個 worker 收到的計算結果渲染到畫面上

plusWorkerChannel.onmessage = (e) => {
  const pResult = document.querySelector('.plus-result');
  pResult.textContent = e.data;
}
minusWorkerChannel.onmessage = (e) => {
  const mResult = document.querySelector('.minus-result');
  mResult.textContent = e.data;
}

小結

利用 BroadcastChannel 可以做到一對多的雙向溝通,相比於 MessageChannel 來說使用上更靈活,而且只允許同源溝通的特性,也較為安全,不會接收到不同源來的惡意程式碼,但缺點是 channel.postMessage 沒有支援 transfer 的使用,代表只能完全複製訊息傳遞,或許不適合需要大量數據的場景。

Reference

Broadcast Channel API


上一篇
Transferable objects - MessagePort
下一篇
Transferable objects - Stream
系列文
網頁的另一個大腦:從基礎到進階掌握 Web Worker 技術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言