Web Worker在專案中的妙用

外星人180發表於2017-11-13

最近在專案中遇到了一些效能問題,為了防止圖片一張一張載入而影響體驗和為了提高效率,需要不斷的提前載入資料和大量圖片,當時我們在專案中使用worker來做效能優化,把計算量比較大和圖片的預載入放入worker中操作。

什麼是 worker

通過使用Web Worker, 我們可以在瀏覽器後臺執行Javascript, 而不佔用瀏覽器自身執行緒。Web Worker可以提高應用的總體效能,並且提升使用者體驗。如果你對worker還不熟悉,請參照,在此就不做過多的介紹了,本文主要是介紹worker的應用場景和效能問題。

如何使用worker預載入圖片

圖片預載入問題分析

  • 一般在專案中不會使用worker來預載入圖片,而是考慮如何實現懶載入圖片,但是基於業務需要所以才使用worker來預載入圖片;預載入圖片可能你用不著,但是本文應該對你瞭解worker有很大幫助;
  • 載入圖片我們有很多方案(不全,如果你還有其他方案希望分享):
    • 通過操作DOM裡面的Img標籤來載入圖片。
    • 也可以通過js的Image物件來載入。
    • 還可以通過ajax來載入。
  • 通過不斷操作DOM來載入圖片是最耗費資源也是最慢的一種方案;通過Image物件來載入比較耗記憶體而且也會佔用主執行緒的資源;把圖片載入放在worker裡面來載入肯定是最合適的,但是在子執行緒裡不能操作DOM,所以Image物件也不能使用,只能考慮使用ajax來實現了,很慶幸的是不管用哪種方案載入圖片都不存在跨域問題。

具體應用

單獨啟動一個worker來載入圖片,每一次請求回來的資料中都通過postMessage給worker,不多說廢話了,直接貼程式碼:

  • Index.js中啟用worker
let w = new Worker("js/workers.js");
 w.onmessage = function (event) {
   /*var img = document.createElement("img");
    img.src = window.URL.createObjectURL(event.data);
    document.querySelector('#result').appendChild(img)
    */
    console.log(event.data);
 };

 w.onerror = function(e){
     e.currentTarget.terminate();
    console.log('erro: ' + e.message);
};複製程式碼
  • worker.js中請求圖片
let arr = [...好多圖片路徑];
for (let i = 0, len = arr.length; i < len; i++) {
    let req = new XMLHttpRequest();
    req.open('GET', arr[i], true);
    req.responseType = "blob";
    //req.setRequestHeader("client_type", "DESKTOP_WEB");
    req.onreadystatechange = () => {
      if (req.readyState == 4) {
      // postMessage(req.response);
    }
  }
  req.send(null);
}複製程式碼

總結很重要

  • 在worker中使用XMLHttpRequest和在主執行緒中使用XMLHttpRequest的效能比較,週末特意用node爬了某網站的500多張圖片的url來做測試得出以下結論:
    • 在主執行緒中每啟動一個XMLHttpRequest請求都會消耗資源,雖然在請求過程中瀏覽器另外開了一個執行緒,但是在互動過程中還是需要消耗主執行緒資源;而使用worker則不會過多佔用主執行緒,只是啟動worker過程時比較耗資源。
    • 大量的XMLHttpRequest請求時,當網速慢時worker中使用XMLHttpRequest和在主執行緒上使用XMLHttpRequest感受不到阻塞,當網速很快時大量請求返還時會出現卡頓現象。
  • 在使用worker的過程中發現,如果worker實列引用為0,該worker空閒後立即會被關閉;如果worker實列引用不為0,該worker空閒也不會被關閉。


相關文章