vite
中使用web worker
1.web worker
介紹
JavaScript
是單線程模型,所有任務(wù)只能在一個(gè)線程上完成莹菱,前面的事情沒有完畢,后面的事情要等待前面的事情處理完畢后才能執(zhí)行吱瘩。但隨著電腦計(jì)算能力的增強(qiáng)道伟,尤其是多核CPU
的出現(xiàn),單線程已無法充分發(fā)揮計(jì)算機(jī)的計(jì)算能力使碾。
web worker
可為 JavaScript
創(chuàng)造多線程環(huán)境蜜徽,允許主線程創(chuàng)建worker
線程,可將一些計(jì)算密集型或高延遲的任務(wù)分配給worker
部逮。worker
線程在后臺(tái)運(yùn)行娜汁,與主線程互不干擾。等到 worker
線程完成計(jì)算任務(wù)兄朋,再把結(jié)果返回給主線程掐禁。如此,可有效提高應(yīng)用性能颅和。
2.原生環(huán)境使用web worker
**原生環(huán)境使用`worker`示例:**
下面代碼功能傅事,主線程發(fā)送兩個(gè)數(shù)字給worker,worker求兩數(shù)字之和峡扩,再將結(jié)果發(fā)送回主線程
`./main.js` `(main thread)`
// 兼容性判斷
if (window.Worker) {
// 1.創(chuàng)建一個(gè)worker
const myWorker = new Worker('worker.js');
// 2.worker消息監(jiān)聽
myWorker.onmessage = e => {
const data = e.data;
console.log(`Message received from worker, sum: ${data.sum}`);
};
// 3.worker異常監(jiān)聽
myWorker.onerror = e => {
console.error(e);
};
// 4.向worker線程發(fā)送數(shù)據(jù)蹭越,注意,只能傳遞一個(gè)參數(shù)教届,如有多個(gè)參數(shù)响鹃,可以包裝成Object
myWorker.postMessage({ a: 1, b: 2 });
// 5.當(dāng)離開頁面的時(shí)候,或者需要結(jié)束worker時(shí)(比如任務(wù)完成時(shí))案训,
// 可以結(jié)束Worker線程买置,不必占用資源
// myworker.terminate();
} else {
// 不支持web worker
console.log("Your browser doesn't support web workers.");
}
`./worker.js` `(worker thread)`
// 1.監(jiān)聽主線程消息
self.onmessage = e => {
// 2.接收來自主線程發(fā)送過來的數(shù)據(jù)
const data = e.data;
console.log(`Message received from main thread, a: ${data.a}, b: ${data.b}`);
const sum = data.a + data.b;
// 3.將結(jié)果發(fā)送給主線程
self.postMessage({ sum });
};
// 4.在worke 線程中也可以監(jiān)聽錯(cuò)誤信息
self.onerror = e => {
console.log(e);
};
// 5.worker線程也可以調(diào)用close結(jié)束worker線程
// self.close();
一些API
說明:
-
主線程可調(diào)用原生
API
Worker()
函數(shù),新建一個(gè)worker
Worker()
構(gòu)造函數(shù)的參數(shù)是一個(gè)腳本文件强霎,該文件就是worker
線程所要執(zhí)行的任務(wù)忿项。var worker = new Worker('work.js');
-
然后,主線程可調(diào)用
worker.postMessage()
方法城舞,向worker
發(fā)消息worker.postMessage('Hello World');
-
接著轩触,主線程通過
worker.onmessage
定義監(jiān)聽函數(shù),接收worker
發(fā)回來的消息worker.onmessage = (e) => { console.log('Received message: ' + e.data); }
-
最后家夺,
worker
完成任務(wù)以后脱柱,主線程就可以把它關(guān)掉worker.terminate();
web worker
注意點(diǎn):
-
同源限制
worker
腳本文件必須與主線程文件同源。 -
API
限制worker
線程的全局對象與主線程不一樣拉馋,無法讀取網(wǎng)頁的DOM
對象褐捻,也無法使用document
掸茅、window
、parent
這些對象柠逞。但是可以使用navigator
對象和location
對象。也可以使用XMLHttpRequest
對象發(fā)出AJAX
請求景馁。 -
通信
worker
線程和主線程不在同一個(gè)上下文環(huán)境板壮,不能共用變量,如果要交互信息合住,必須通過postMessage
完成绰精。
3.vite
中使用web worker
vite
也支持web worker
,不過其中存在一些陷阱透葛,官方提供了兩種使用web worker的方式笨使,官方文檔傳送門:
-
帶有查詢后綴的導(dǎo)入
import Worker from './worker.js?worker' const worker = new Worker()
此方式在
vite2.x
版本下,可在測試環(huán)境和正式環(huán)境正常使用(親測) -
通過構(gòu)造器導(dǎo)入(官方推薦方式)
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module', })
此方式在
vite2.x
版本下僚害,只能在測試環(huán)境正常工作硫椰,無法用于生產(chǎn)環(huán)境(親測)
在vite
中使用的完整示例,依然是實(shí)現(xiàn)求和功能:
main.js
(也可以是.vue
文件中的任意主線程腳本)
import myWorker from './myWorker?worker&inline';
let worker = null;
if (window.Worker) {
worker = new myWorker();
worker.onmessage = e => {
const data = e.data;
console.log(data.sum);
};
worker.onerror = e => console.error(e);
}
if (worker) {
worker.postMessage({ a: 1, b: 2 });
}
myWorker.js
(需要處于src
目錄下萨蚕,如果處于public
目錄將無法使用靶草,親測)
self.onmessage = e => {
const data = e.data;
const sum = data.a + data.b;
self.postMessage({ sum });
};
self.onerror = e => console.log(e);