Web Workers 調用 API,減輕主執行緒負擔

Web Workers 調用 API,減輕主執行緒負擔

本篇要解決的問題

這陣子,不知道是不是演算法的關係,看到的文章很常出現「Web Workers」這個詞,查了一下後發現,Web Workers 是一個連 IE10 都支援的功能,看來是歷史悠久牌子老、街頭巷尾都稱讚的 API,就想說來看一下。

看完幾篇教學文,發現應該再早點知道的,可以處理工作上遇到的一些問題。

Web Workers 可以解決的問題,August 想到的有以下:

  • 調用回應時間比較長的 API
  • 在背後收集使用者的行為
  • 想提前載入頁面上其它區塊會需要的資料

總之,就是可以把一些處理時間較長、不必要在頁面一載入就撈取的資料,丟給另一條執行緒去處理,不讓主執行緖有阻塞,進而減少使用者在操作上會有的卡頓感。

本篇會先簡單說明什麼是 Web Workers,接著是使用方法,以及附上 August 最想應用的方式:調用 API 的 Demo。


簡單解釋 Web Workers

本段最後會提供的參考資源,把 Web Workers 都解釋得很清楚了,所以這段的說明,會用 August 的方式來簡單形容。

我們假設瀏覽器是一間便利商店,這間便利商店因為慣老闆的原因(咦?),只有一位員工,這位員工就是 JS 的主執行緒。超商員工是很辛苦的,又要上架商品、又要結帳、又要煮咖啡、又要幫顧客找網購的商品,然後薪水才這麼一點(哎這樣說好嗎?)

通常,「找網購商品」這件事是耗時最久的,因為員工要在一堆的包裹裡找到特定顧客的那件,耗掉的時間有可能會阻礙結帳,讓結帳的人流排到店門口。而這件事就是網頁上最常發生的調用 API,是不是很像?在 API 回應我們特定需要的資料前,我們就只能等,還什麼事情都不能做。

後來,老闆覺得這樣累績負面評價有害公司的名聲(如:讀取時間會影響 SEO 排名),所以他選擇了最快的解決方式:再找一位員工來,讓他在後面協助處理找包裹這件事,如果煮咖啡也覺得久,那就讓他順便處理煮咖啡好了。這位新來的員工,就是這篇在講的 Web Workers。

Web Workers,就是在網頁上除了 JS 主執行緒之外的另一條執行緒。

參考資源:


Web Workers 使用

Web Workers 的使用方式很簡單,整理成下圖:

Web Workers 使用說明

網頁的 JS 跟 Web Workers 溝通的方式就是 postMessageonmessage

postMessage 是傳送資料。

onmessage 是接收資料。

我們先看網頁上的主要 JS,我們命名為 main.js。

main.js

const worker = new Worker('worker.js');

// 傳送資料
work.postMessage({ name: 'August' });

// 接收 Web Workers 來的資料
worker.onmessage = e => {
  const data = e.data;
  console.log(data);
}

接著來看 Web Workers 的內容,我們命名為 work.js。

work.js

importScripts('https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.0/axios.min.js');

// 接收資料
self.onmessage = e => {
  const data = e.data;
  if(data) {
    const result = axios.post(...); // 調用 API
    self.postMessage(result); // 傳送資料
  }
}

是的,你沒看錯,我也沒寫錯,work.js 在 importScript 時,可以引用 CDN,而且寫程式的方式可以用 ES6。

這點因為看的教程上都沒有,是問了 ChatGPT 後,再透過實作去嘗試才知道的。


Web Workers 使用範例:調用 API

最後這段,是 August 寫了一個 Demo,讓 Web Workers 來處理調用 API 的部份,然後回傳給主執行緒,讓網頁上呈現結果。

完整的原始碼已放上 GitHub,不過有一段 August 想列出來,就是 Web Workers 處理 API 的部份。

原本 August 自己寫了一個,結果丟給 ChatGPT 看,想問它還有沒有可以優化的地方,殊不知,它就給了一個加上「限制最大請求數」的方式,覺得這樣子的方式更符合實際需求,就採用了。


Demo、原始碼

本篇的 Demo 跟原始碼,都放上 GitHub,取用前請分享此篇文章,或對 GitHub 專案點個星星,你的小小舉動,對本站都是大大的鼓勵。

Demo:https://letswritetw.github.io/letswrite-web-workers/

原始碼:https://github.com/letswritetw/letswrite-web-workers