在web?worker中使用fetch實(shí)例詳解
1.Web Worker意義
由于 JS 是單線程的,費(fèi)時的 JS 操作將會導(dǎo)致整個頁面的阻塞。Web Worker 提供了創(chuàng)建多線程的方法,將一些耗時且 UI 無關(guān)的工作交給 worker,可提高頁面的使用體驗(yàn)。
限制:
同源策略:worker 線程執(zhí)行的腳本要和當(dāng)前頁面同源
API 限制:
- 不能操作 DOM
- 不能使用 window 的全局變量,但可以使用 navigator 和 location 對象
- 不能使用 alert、confirm 方法
- 無法讀取本地文件
和主線程不在一個上下文環(huán)境,通訊要通過 postMessage
完成
2. 主線程的使用
創(chuàng)建
創(chuàng)建一個子線程,要傳入一個腳本的 URL。如果該腳本加載失敗,則 Worker 會靜默失敗
const worker = new Worker('url');
如果要在本文件中描述執(zhí)行的內(nèi)容,可以用 Blob 和 window.URL.createObjectURL 生成一個 URL
function createWorker(f) { const blob = new Blob(['(' + f.toString() +')()']); const url = window.URL.createObjectURL(blob); const worker = new Worker(url); return worker; }
通信
- 主線程 => 子線程
worker.postMessage(param);
參數(shù)可以是任意類型,包括二進(jìn)制數(shù)據(jù)。但傳遞是拷貝形式而不是引用形式。因此對于大數(shù)據(jù)會存在性能問題。
- 子線程 => 主線程
worker.onmessage = function (event) { console.log('Received message ' + event.data); }
錯誤處理
worker.onerror(function (e) { console.log([ 'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message ].join('')); });
關(guān)閉
worker.terminate();
3. 子線程的使用
子線程中無法使用 window,self
代表全局對象
和主線程的通信
- 主線程 => 子線程
self.addEventListener('message', function (e) { self.postMessage('Received: ' + e.data); }, false);
- 子線程 => 主線程
self.postMessage('something');
加載其他腳本
在子線程中加載其他腳本:
importScripts('script1.js', 'script2.js');
關(guān)閉
self.close();
4. 在WebWorker中使用fetch
網(wǎng)絡(luò)請求是和DOM無關(guān)且可能耗時較長的操作,worker線程支持使用Fetch,是適合放在worker中進(jìn)行的操作。
而要在worker中使用fetch,如果每次都要自己處理線程間的通信的話,會十分麻煩,因此我對通信進(jìn)行了封裝,寫成了一個可以直接使用的庫。
安裝依賴:
npm i web-worker-fetch
使用時先實(shí)例化一個WF對象,然后就可以像使用fetch一樣在worker中使用fetch:
import WebWorkerFetch from "web-worker-fetch"; const wf = new WebWorkerFetch(); wf.fetch("url", { method: "POST", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, *cors, same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, *same-origin, omit headers: { "Content-Type": "application/json" // 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: "follow", // manual, *follow, error referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url body: JSON.stringify(data) // body data type must match "Content-Type" header }).then((res) => console.log(res));
除此之外,借鑒 axios
的思路,配置中可以提供 requestInterceptor
和 responseInterceptor
,對請求參數(shù)和返回數(shù)據(jù)做統(tǒng)一處理
5. 實(shí)現(xiàn)思路
這個庫的封裝主要是解決了兩個問題:
- 發(fā)送請求時如何把參數(shù)傳遞給worker線程
- 請求結(jié)束后如何從worker線程獲取結(jié)果
對于第一個問題,主線程使用 ostMessage
向worker線程傳遞參數(shù)。
對于第二個問題,worker線程通過 self.postMessage
向主線程傳遞消息,主線程通過 worker.onmessage
監(jiān)聽消息。
此時就引出了問題所在:如果多次使用 wf.fetch
發(fā)送請求,那么在一個請求完成后,worker線程觸發(fā)的消息將讓所有請求處都認(rèn)為請求已完成。
因此,在每次請求時,使用一個fetchId確定該請求做唯一性。將該id傳給worker線程,后續(xù)worker線程向主線程通信時也會帶上這個id。
在主線程中監(jiān)聽onmessage事件時,判斷id是否和自己的請求id一致,只有在相同時才做處理。
具體的實(shí)現(xiàn)大家可以移步倉庫源碼,實(shí)際上也非常簡單。
以上就是在web worker中使用fetch實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于web worker使用fetch的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序 教程之wxapp視圖容器 scroll-view
這篇文章主要介紹了微信小程序 教程之wxapp視圖容器 scroll-view的相關(guān)資料,需要的朋友可以參考下2016-10-10document 和 document.all 分別什么時候用
document 和 document.all 分別什么時候用...2006-06-06