iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0

昨天介紹了 Shared worker 的基本用法,今天打算寫個範例來了解 Shared worker 的生命週期

目的

  1. 了解如何使用 Shared workerShared worker 的生命週期

說明

  1. 範例中有兩個頁面,分別為 Home pageNew page,兩個頁面基本上是一樣的,畫面上都有 +1, -1 按鈕,按下去後分別可以傳送訊息給 worker 改變 worker 中的 count 變數
  2. 兩個頁面都會接收由 worker 傳來的 count 變數,由於 count 變數存在於 worker 線程中,因此只要其中一個頁面的改變 count,另一個頁面也能馬上接收到 count 值的改變

範例 Demo

https://ithelp.ithome.com.tw/upload/images/20231003/20162687ygRoVaOjGP.png

https://ithelp.ithome.com.tw/upload/images/20231003/20162687BDG5H2vdSj.png

建立 Shared worker 並傳送訊息

首先建立 Shared worker,並分別在按下按鈕後,postMessage +1-1

// 主線程
const worker = new SharedWorker('public/worker.js');

Array.from(document.querySelectorAll('button')).forEach((button) => {
  button.addEventListener('click', (e) => {
    const { className } = e.target;

    switch (className) {
      case 'plus':
        // 傳遞訊息到 worker (+1)
        worker.port.postMessage(1);
        break;
      case 'minus':
        // 傳遞訊息到 worker (-1)
        worker.port.postMessage(-1);
        break;
      default:
        break;
    }
  });
});

Shared worker 接收訊息

worker 線程中會定義兩個參數

  • count: 計算點擊數
  • ports: 儲存連接到 worker 的所有 port,方便之後統一發送訊息

然後當 worker 接收到訊息後,更新 count 的值,並把最新的 count 發送到每個與 worker 有連線的主線程

// worker 線程
let count = 0;
const ports = [];

// 將訊息傳遞到每個與 worker 有連線的主線程
const postMessageToAllPorts = (data) => {
  ports.forEach((port) => {
    port.postMessage(data);
  });
};

onconnect = (e) => {
  const port = e.ports[0];
  ports.push(port);
  postMessageToAllPorts(count);

  port.addEventListener("message", (e) => {
    // 接收訊息執行 +1 或 -1
    count += e.data;
    postMessageToAllPorts(count);
  });

  // 使用 port.addEventListener 寫法時,需要手動 start
  port.start();
};

主線程接收訊息

主線程接收到訊息後,將最新的 count 顯示在畫面上

worker.port.onmessage = (e) => {
  document.querySelector('.result').textContent = e.data;
};

結果

  1. Shared worker 接收到訊息時,會送出最新的 count 到所有連接的頁面,所以任一頁面改變 count 值後,可以看到其他頁面都會顯示最新的 count
  2. 由於 Shared worker 可以在同源下的不同頁面被呼叫使用,因此只要這些頁面其中一個還開啟著,Shared worker 檔案裡的變數就都還是存在的,因此重整頁面後 count 值的變化會有以下兩種狀況:
  • case 1.
    兩個頁面都開著的狀態下,重整其中一個頁面,count 的值會是最新的
  • case 2.
    只剩單獨一個頁面開著的狀態下,重整頁面瞬間 Shared worker 就會被卸載了,所以重整後的 count 值會回到初始的 0

補充小知識

  1. 在 Chrome 中除錯 Shared worker
    Shared worker 中執行 console.log() 時,預設無法在 devtoolconsole 面板中看到,這時可以在 Chrome 瀏覽器輸入 chrome://inspect/#workers,接著點擊 inspect 就可以看到 worker 中 log 出來的訊息了
    How to debug web workers

上一篇
共享的 Web worker - Shared worker
下一篇
在 Javascript 中共享記憶體 - SharedArrayBuffer
系列文
網頁的另一個大腦:從基礎到進階掌握 Web Worker 技術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言