最近在專案中遇到了一些效能問題,為了防止圖片一張一張載入而影響體驗和為了提高效率,需要不斷的提前載入資料和大量圖片,當時我們在專案中使用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空閒也不會被關閉。