這陣子,不知道是不是演算法的關係,看到的文章很常出現「Web Workers」這個詞,查了一下後發現,Web Workers 是一個連 IE10 都支援的功能,看來是歷史悠久牌子老、街頭巷尾都稱讚的 API,就想說來看一下。
看完幾篇教學文,發現應該再早點知道的,可以處理工作上遇到的一些問題。
Web Workers 可以解決的問題,August 想到的有以下:
總之,就是可以把一些處理時間較長、不必要在頁面一載入就撈取的資料,丟給另一條執行緒去處理,不讓主執行緖有阻塞,進而減少使用者在操作上會有的卡頓感。
本篇會先簡單說明什麼是 Web Workers,接著是使用方法,以及附上 August 最想應用的方式:調用 API 的 Demo。
本段最後會提供的參考資源,把 Web Workers 都解釋得很清楚了,所以這段的說明,會用 August 的方式來簡單形容。
我們假設瀏覽器是一間便利商店,這間便利商店因為慣老闆的原因(咦?),只有一位員工,這位員工就是 JS 的主執行緒。超商員工是很辛苦的,又要上架商品、又要結帳、又要煮咖啡、又要幫顧客找網購的商品,然後薪水才這麼一點(哎這樣說好嗎?)
通常,「找網購商品」這件事是耗時最久的,因為員工要在一堆的包裹裡找到特定顧客的那件,耗掉的時間有可能會阻礙結帳,讓結帳的人流排到店門口。而這件事就是網頁上最常發生的調用 API,是不是很像?在 API 回應我們特定需要的資料前,我們就只能等,還什麼事情都不能做。
後來,老闆覺得這樣累績負面評價有害公司的名聲(如:讀取時間會影響 SEO 排名),所以他選擇了最快的解決方式:再找一位員工來,讓他在後面協助處理找包裹這件事,如果煮咖啡也覺得久,那就讓他順便處理煮咖啡好了。這位新來的員工,就是這篇在講的 Web Workers。
Web Workers,就是在網頁上除了 JS 主執行緒之外的另一條執行緒。
參考資源:
Web Workers 的使用方式很簡單,整理成下圖:
網頁的 JS 跟 Web Workers 溝通的方式就是 postMessage
、onmessage
postMessage
是傳送資料。
onmessage
是接收資料。
我們先看網頁上的主要 JS,我們命名為 main.js。
main.js
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 後,再透過實作去嘗試才知道的。
最後這段,是 August 寫了一個 Demo,讓 Web Workers 來處理調用 API 的部份,然後回傳給主執行緒,讓網頁上呈現結果。
完整的原始碼已放上 GitHub,不過有一段 August 想列出來,就是 Web Workers 處理 API 的部份。
原本 August 自己寫了一個,結果丟給 ChatGPT 看,想問它還有沒有可以優化的地方,殊不知,它就給了一個加上「限制最大請求數」的方式,覺得這樣子的方式更符合實際需求,就採用了。
本篇的 Demo 跟原始碼,都放上 GitHub,取用前請分享此篇文章,或對 GitHub 專案點個星星,你的小小舉動,對本站都是大大的鼓勵。