iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0

昨天學習了 Channel messaging 在主頁面與 iframe 間的訊息傳遞,而今天就讓我們來看看 MessagePort 怎麼在 web worker 中發揮 Transferable object 的作用吧。

以下範例創建兩個 worker,並且將 MessageChannel 中產生的兩個 port 分別轉移到這兩個 worker,使他們之間可以互相通信。

範例 Demo

index.mjs (主線程)

// 首先我們創建兩個 worker
const worker1 = new Worker('public/worker1.mjs');
const worker2 = new Worker('public/worker2.mjs');

// 接著將 MessagePorts 分別轉移到 worker 1 & 2
const channel = new MessageChannel();
worker1.postMessage('INIT', [channel.port1]);
worker2.postMessage('INIT', [channel.port2]);

worker1.mjs

let port1;

const init = (port) => {
  // 初始化,接收 MessageChannel 的 port
  port1 = port;
  port1.onmessage = (e) => {
    console.log('worker1 中的 port1 接收到的資料', e.data);
  };
};

const sendMessage = (data) => {
  // 之後從主線程發送的資料,會從 port1 傳到 port2
  console.log('worker1 接收到的資料', data);
  port1.postMessage(data); // 這裡將資料直接傳遞到 port2 (也就是 worker2)
};

self.onmessage = (e) => {
  const port = e.ports[0];

  switch (e.data) {
    case 'INIT':
      init(port);
      break;
    default:
      sendMessage(e.data);
      break;
  }
};

worker2.mjs

let port2;

const init = (port) => {
  // 初始化,接收 MessageChannel 的 port
  port2 = port;
  port2.onmessage = (e) => {
    console.log('worker2 中的 port2 接收到的資料', e.data);
  };
};

const sendMessage = (data) => {
  // 之後從主線程發送的資料,會從 port2 傳到 port1
  console.log('worker2 接收到的資料', data);
  port2.postMessage(data); // 這裡將資料直接傳遞到 port1 (也就是 worker1)
};

self.onmessage = (e) => {
  const port = e.ports[0];

  switch (e.data) {
    case 'INIT':
      init(port);
      break;
    default:
      sendMessage(e.data);
      break;
  }
};

以上範例,我們先將 MessageChannel 創建出來的 port1port2 分別轉移到 worker1worker2 中使用,讓 worker 1worker 2 藉由 port 直接溝通,接著每次主線程發送訊息到 port1port2 時,都會再轉送到另一個 port

小結

由這個小範例可以看到 MessageChannel 創建出來的 port 可以任意分給主線程或是 worker 線程,達到兩者之間的訊息溝通。

Reference

MessageEvent: ports property


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

尚未有邦友留言

立即登入留言