js是單線程語言,無法開啟多個線程同時執(zhí)行。HTML5中夺脾,瀏覽器提供了一種新特性web worker鼓黔,讓我們可以在頁面主運行的 JavaScript 線程中加載運行另外單獨的一個或者多個 JavaScript 線程。這樣谎脯,在主線程處理頁面渲染和交互的同時葱跋,web worker可處理一些復雜計算,當有結果后通知給主線程。
專用/共享
專用線程Dedicated Worker:一個worker線程對應一個js主線程娱俺。瀏覽器支持率很高际看。
共享線程 Shared Worker:一個worker線程可以被多個同源js主線程使用。需要指定port矢否,顯示打開后才能使用仲闽。瀏覽器支持率較低,較少使用僵朗。
// 主線程
const sharedWorker = new SharedWorker('./sharedWorker.js');
sharedWorker.port.onmessage = function(e) {
// 業(yè)務邏輯
}
sharedWorker.port.start() // 需要顯式打開
sharedWorker.port.postMessage([10, 24])
// Worker 線程
onconnect = function (e) {
let port = e.ports[0]
port.onmessage = function (e) {
if (e.data.length > 1) {
port.postMessage(e.data[1] - e.data[0])
}
}
}
由于共享線程sharedWorker目前支持情況較差赖欣,下文主要介紹專用線程worker。
使用
// main.js
// 實例化一個worker
const worker = new Worker('../src/worker.js');
// 監(jiān)聽message事件
worker.onmessage = e => {
console.log(e.data); // "Polo"
}
// 錯誤處理
// 將普通錯誤冒泡上來
worker.onerror = e => {
console.log(e); // a is undefined
}
// onmessageerror 監(jiān)聽發(fā)送的數據不能被反序列化錯誤
// 發(fā)送數據事件
worker.pushMessage("Marco");
// 立即終止worker線程中全部操作
worker.terminate();
// worker.js
// 監(jiān)聽message事件
onmessage = e => {
console.log(e.data); // "Marco"
console.log(a) // 拋出錯誤
// 發(fā)送數據事件
pushMessage("Polo");
}
// 關閉當前worker線程
close();
// 引用外部腳本
importScripts(urlA, urlB);
worker和主線程中的數據傳遞验庙,是通過復制數據顶吮,將數據的副本用于傳輸,(序列化/反序列化粪薛,瀏覽器中主要通過JSON編碼/解碼)悴了,所以是兩份相互獨立的數據。
可以獲取到部分瀏覽器提供的 API :
setTimeout()违寿, clearTimeout()湃交, setInterval()藤巢, clearInterval()
:有了設計個函數搞莺,就可以在 Worker 線程中執(zhí)行定時操作了;
XMLHttpRequest
對象:意味著我們可以在 Worker 線程中執(zhí)行 ajax 請求掂咒;
navigator
對象:可以獲取到 ppName才沧,appVersion,platform绍刮,userAgent 等信息温圆;
location
對象(只讀):可以獲取到有關當前 URL 的信息;
局限性
- 不能訪問DOM
- 沒有window全局對象
- 同源限制:js主線程和worker必須同源
本地調試孩革,也需要起服務岁歉,可以用browser-sync。
使用場景
- 懶加載
- 文本分析
- 流媒體數據處理
- canvas 圖形繪制
- 圖像處理
- ...