作者:刮刮樂打工仔
https://juejin.cn/post/7439918857492660259
前提:什么是線程???
線程(英語:thread)是操作系統[1]能夠進行運算調度[2]的最小單位。它被包含在進程[3]之中,是進程[4]中的實際運作單位。一條線程指的是進程[5]中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。
線程是獨立調度和分派的基本單位。
同一進程中的多條線程將共享該進程中的全部系統資源,如虛擬地址空間,文件描述符[6]和信號處理[7]等等。但同一進程中的多個線程有各自的調用棧[8](call stack),自己的寄存器環境(register context),自己的線程本地存儲(thread-local storage)。
JavaScript單線程
JavaScript設計成單線程目的:為了防止多個線程同時操作DOM,帶來渲染沖突問題。
但是遇見大量計算會使頁面卡頓,用戶體驗不佳
就引出本篇的主題Web Worker
??Web Worker??
Web Worker
允許我們在 js 主線程之外開辟新的 Worker 線程。 因為是獨立的線程,Worker 線程與 js 主線程能夠同時運行,互不阻塞。 如果有大量運算任務時,可以把運算任務交給 Worker 線程去處理,當 Worker 線程計算完成,再把結果返回給 js 主線程。
js主線程只用專注處理業務邏輯,Worker處理大量復雜計算,從而減少了主線程阻塞 時間,提高運行效率和提升用戶體驗。
Web Worker用法
const worker = new Worker(path, options);
path
js腳本的路徑地址(遵守同源策略),否則會拋出SECURITY_ERR
類型錯誤
type
worker 類型。該值可以是 classic
或 module
。 默認值 classic
credentials
worker憑證。該值可以是 omit
, same-origin
,或 include
。默認值 omit
(不要求憑證)
主線程與Worker參數之間參數傳遞
index.html
const myWorker = new Worker('/worker.js');
myWorker.addEventListener('message', e => {
console.log(e.data);
});
myWorker.postMessage('這里是主線程');
worker.js
// self是worker的全局對象,它繼承了WorkerGlobalScope的屬性和方法
self.addEventListener('message', e => {
console.log(e.data);
self.postMessage('這里是worker線程');
});
控制臺輸出結果
線程監聽
index.html
const myWorker = new Worker('/worker.js');
myWorker.addEventListener('error', err => {
console.log(err.message);
});
myWorker.addEventListener('messageerror', err => {
console.log(err.message)
});
work.js
self.addEventListener('error', err => {
console.log(err.message);
});
self.addEventListener('messageerror', err => {
console.log(err.message);
});
線程關閉
index.html
const myWorker = new Worker('/worker.js');
myWorker.terminate(); // 關閉worker
worker.js
self.close();
線程內部引用其它文件
worker 線程中利用 importScripts()
方法加載js文件,此方法加載的js文件不受同源策略約束
utils.js
const fn = ()=>{
console.log("hello, world")
}
worker.js
// 使用方法:importScripts(path1, path2, ...);
importScripts('./utils.js
// 直接使用
fn()
如果你的utils是ESModule, 生成Worker實例的時候,type指定類型為module, 這個時候你的word.js需把頂級對象self暴露出去
index.html
const worker = new Worker('/worker.js', {
type: 'module' // 指定 worker.js 的類型
});
worker.js
...
export default self; // 只需把頂級對象self暴露出去即可
傳參注意事項
??SharedWorker??
SharedWorker
接口代表一種特定類型的 worker,可以從幾個瀏覽上下文中訪問,例如幾個窗口、iframe 或其他 worker。它們實現一個不同于普通 worker 的接口,具有不同的全局作用域,`SharedWorkerGlobalScope`[9] 。
實現多頁面通信
a.html
const worker = new SharedWorker('calculator.js');
worker.port.onmessage = function(event) {
console.log(event.data); // 接收SharedWorker返回的結果
};
worker.port.postMessage({ type: 'add', operands: [2, 3] }); // 向SharedWorker發送消息
b.html
const worker = new SharedWorker('calculator.js');
worker.port.onmessage = function(event) {
console.log(event.data); // 接收SharedWorker返回的結果
};
worker.port.postMessage({ type: 'multiply', operands: [4, 5] }); // 向SharedWorker發送消息
calculator.js
const ports = [];
self.onconnect = function(event) {
const port = event.ports[0];
ports.push(port);
port.onmessage = function(event) {
const message = event.data;
const result = calculate(message.type, message.operands); // 執行計算任務
ports.forEach(port => port.postMessage(result)); // 將結果發送給所有連接的頁面
};
};
function calculate(type, operands) {
if (type === 'add') {
return operands.reduce((a, b) => a + b, 0);
} elseif (type === 'multiply') {
return operands.reduce((a, b) => a * b, 1);
}
}
??Web Worker(性能優化)總結??
- 多線程處理:Web Worker 允許在獨立的線程中運行 JavaScript 代碼,這樣可以充分利用多核處理器和提高性能。
- 避免阻塞主線程:通過將一些密集計算或長時間運行的任務放在 Web Worker 中,可以避免阻塞主線程,提高頁面的響應性。
- 異步處理:Web Worker 提供了一個與主線程并行執行腳本的環境,可以處理一些異步任務,如網絡請求、數據處理等,從而提高性能。
- 數據共享:Web Worker 可以通過消息傳遞機制與主線程通信,還可以共享數據,這樣可以更高效地處理復雜的數據操作。
- 模塊化設計:將復雜的任務拆分成多個模塊,在不同的 Web Worker 中并行處理,可以提高代碼的可維護性和性能。
- 資源加載:Web Worker 無法訪問 DOM,因此在使用 Web Worker 時需要注意不能直接操作 DOM 元素,避免因此導致性能問題。
- 性能測試:在使用 Web Worker 優化性能時,需要進行性能測試和監控,以確保 Web Worker 的引入確實提高了頁面性能。
該文章在 2025/1/24 11:05:05 編輯過