Web Worker使用指南 解鎖瀏覽器多線程 ,提升前端性能的利器

文章目錄

  • 前言
  • 一、什么是 Web Worker
  • 二、適用場景
    • 1、CPU 密集型計算
    • 2、圖像/視頻處理
    • 3、實時數據流處理(高頻場景)
    • 4、后臺文件操作
    • 5、復雜狀態機/AI邏輯(游戲開發)
    • 6、長輪詢與心跳檢測
    • 7、WebAssembly 加速
    • 8、WebGL 與 Canvas 渲染
    • 總結
  • 三、Web Worker API詳解
    • 快速上手示例:
    • 關鍵API詳解
      • 3.1、主線程中使用:
        • (1)創建實例
        • (2)事件監聽
        • (3)實例方法
          • 示例:
      • 3.2、子線程中使用:
        • (1)事件監聽
        • (2)向主線程發送消息
        • (3)終止Worker
        • (4)導入外部腳本
    • 總結
      • 1、創建和使用 Worker
      • 2、消息傳遞機制
      • 3、Worker 線程的限制
    • 注意事項
  • 四、訪問瀏覽器 API
    • Worker無法訪問的瀏覽器 API
      • 1. DOM 操作相關
      • 2. 窗口與視圖相關
      • 3. 渲染與動畫相關
      • 4、部分全局對象
    • Worker 可使用的API
      • 1、數據存儲
      • 2. 網絡請求
      • 3. 定時器
      • 4. 多線程協作
  • 五、構建工具中使用Worker
    • 1、Vite
      • 方法1:(添加?worker后綴)
      • 方法2:(new URL)
    • 2、Webpack 5
    • 3、Webpack 4
  • 總結


前言

在現代Web開發中,隨著應用復雜度的增加,主線程(UI線程)的負擔越來越重。JavaScript的單線程特性意味著耗時任務會阻塞用戶交互,導致界面卡頓。Web Worker 的出現為我們提供了一種解決方案,它允許在主線程之外創建后臺線程,從而讓我們能夠并行處理任務,提升應用的響應性和流暢性。本文將深入解析Web Worker的使用技巧,包括在Vite等現代工程化環境中的實踐。

請添加圖片描述


一、什么是 Web Worker

Web Worker 是 HTML5 規范中引入的一項功能,它允許在瀏覽器中創建獨立于主線程的 JavaScript 線程。這些線程可以在后臺運行,執行復雜的計算或 I/O 操作,而不會阻塞主線程的執行。這樣,即使在處理大量數據或執行復雜計算時,頁面仍然能夠保持流暢的交互體驗。

Web Worker 的主要特點包括:

  • 獨立于主線程的 JavaScript 線程(子線程),不阻塞UI渲染
  • 獨立上下文:Worker 擁有自己的全局對象self,非window
  • 通過消息機制與主線程通信
  • 無法直接操作DOM
  • 無法訪問document、window、localStorage/sessionStorage等瀏覽器 API
  • 可以訪問部分瀏覽器 API(如 XMLHttpRequest、localStorage 等)
  • 同源限制:Worker 腳本必須與主線程同源
  • 支持現代ES6+語法

二、適用場景

1、CPU 密集型計算

執行大量計算(如數學運算、數據排序、加密解密)時,主線程會被阻塞導致頁面卡頓。例如:

  • 處理 100 萬條以上的金融交易數據
  • 處理上萬條的表格數據排序
  • 處理上萬條的echart數據格式
  • 模擬物理系統或執行復雜算法

2、圖像/視頻處理

像素級圖像濾鏡應用(如模糊、銳化)、視頻編解碼

3、實時數據流處理(高頻場景)

物聯網傳感器流、實時日志分析、WebSocket消息處理

4、后臺文件操作

Excel/CSV文件解析,文件上傳

5、復雜狀態機/AI邏輯(游戲開發)

NPC行為決策樹、物理引擎模擬、戰斗傷害計算

6、長輪詢與心跳檢測

定期執行網絡請求或狀態檢查,避免阻塞 UI。在線狀態檢測、定時數據同步、任務進度監控等

7、WebAssembly 加速

結合 WebAssembly 在 Worker 中執行高性能計算。例如:利用 WebAssembly 加速視頻處理、運行輕量級神經網絡模型

8、WebGL 與 Canvas 渲染

使用 OffscreenCanvas 將渲染任務轉移到 Worker。例如:復雜圖形繪制、3D 場景渲染等

總結

Web Worker 的核心價值在于將計算密集型、耗時操作與UI 渲染分離,提升應用響應性,通過結合 Transferable Objects、OffscreenCanvas 和 WebAssembly 等技術,Web Worker 能進一步釋放瀏覽器的多核性能,為用戶提供流暢的交互體驗。


三、Web Worker API詳解

快速上手示例:

計算1+2+3+4+…+1000000000的結果

main.js(主線程)

// main.js (主線程)const worker = new Worker('./worker.js');// 發送消息給Worker
worker.postMessage('start');// 接收Worker的消息
worker.onmessage = event=> {console.log('計算結果為:'+ event.data);
};// 錯誤處理
worker.onerror =error=> {console.error('error:', error.message);
};

worker.js (Worker線程)

//worker.js (子線程)//接收主線程消息
self.onmessage = event=> {if (event.data === 'start') {// 執行復雜計算let result = 0;for (let i = 0; i < 1000000000; i++) {result += i;}// 發送結果給主線程self.postMessage(result);}
};

Web Worker 創建的線程是獨立于主線程的,它有自己的執行上下文和事件循環。Worker 線程無法直接訪問 DOM 或主線程的全局變量,但可以通過消息傳遞機制與主線程通信


關鍵API詳解

3.1、主線程中使用:

(1)創建實例
const worker = new Worker(scriptURL, [options]);
  • scriptURL :指定 Worker 線程執行的 JavaScript 文件的 URL(必須)

    要求:
    (1)必須是同源的 URL(與主頁面相同的協議、域名和端口)
    (2)可以是相對路徑或絕對路徑
    (3)支持數據 URL(Data URL)和 Blob URL

    示例:

// 相對路徑
const worker = new Worker('../worker.js');// 絕對路徑
const worker = new Worker('/public/worker.js');// 完整 URL
const worker = new Worker('https://example.com/worker.js');// Blob URL(用于內聯 Worker)
const blob = new Blob(['self.onmessage = e => self.postMessage(e.data);'], {type: 'application/javascript'});
const worker = new Worker(URL.createObjectURL(blob));
  • options:可選配置對象

    可選屬性:

屬性名說明類型默認值可選值
type指定 Worker 的類型Stringclassicclassic (傳統腳本類型)、module:(ES6 模塊類型,支持 import語法,構建工具內開發常配置)
credentials模塊腳本的憑證(僅當 type: ‘module’ 時有效)Stringsame-originomit(不帶憑證)、same-origin(同源帶憑證)、include(跨域帶憑證)
nameWorker 實例標識名(可通過 self.name 在 Worker 內部訪問)String————

示例:

//子線程使用 ES6 模塊類型
const worker = new Worker('worker-module.js', { type: 'module' });
// worker-module.js (ES6 模塊)
import { helperFunction } from './utils.js';self.onmessage = event => {const result = helperFunction(event.data);self.postMessage(result);
};

創建成功后返回一個 Worker 對象實例

(2)事件監聽
  • onmessage:消息事件處理函數,監聽來自子線程消息,回調通過event.data獲取數據
  • onerror:錯誤事件處理函數

上述事件也可以使用addEventListener方法代替:

// main.js
const worker = new Worker('worker.js');
//監聽子線程消息
worker.onmessage = event=> {console.log('來自子線程消息', event.data);
};
//或寫成如下
worker.addEventListener('message', e => {console.log(e.data,'來自子線程消息');
});//錯誤事件處理
worker.onerror = e=> {console.log(e,'執行錯誤');
};
//或寫成如下
worker.addEventListener('error',e=>{console.log(e,'執行錯誤');
})
(3)實例方法
  • postMessage(message, [transfer]): 向 Worker(子線程)發送消息
  • terminate: 立即終止 Worker 線程
  • addEventListener:事件監聽方法
示例:

1、主線程向子線程發送消息

// 主線程發送消息
worker.postMessage({ type: 'CALC_FIB', value: 40 });

2、終止Worker

// 主線程中終止
worker.terminate();

3.2、子線程中使用:

注意子線程中,全局對象為self,非window

(1)事件監聽

跟主線程一樣通過onmessage 監聽來自主線程消息,回調通過event.data獲取數據

// worker.js 
//消息事件處理函數
self.onmessage = event => {console.log('接收來自主線程消息', event.data);};
(2)向主線程發送消息

跟主線程一樣通過postMessage給主線程發送消息

self.postMessage('來自子線程消息');
(3)終止Worker
// Worker內部自終止
self.close();
(4)導入外部腳本

在 Worker 內部可以使用importScripts()方法導入外部腳本:

importScripts('script1.js', 'script2.js');

總結

1、創建和使用 Worker

創建 Worker 需要一個獨立的 JavaScript 文件,主線程通過 Worker() 構造函數初始化這個 Worker

2、消息傳遞機制

主線程和 Worker 之間通過 postMessage() 方法發送消息,并通過 onmessage 事件監聽消息。消息可以是基本數據類型、對象或數組。如果是引用類型,數據會被序列化和反序列化,在兩端創建獨立的副本(深拷貝)。

3、Worker 線程的限制

無法直接訪問以下主線程資源:DOM 元素、window、document、parent 等對象


注意事項

1、同源限制:Worker 腳本必須與主頁面同源,否則會拋出安全錯誤
2、路徑問題:Worker 腳本中的相對路徑是相對于腳本本身,而非主頁面
3、調試技巧:使用 name 選項為 Worker 命名,便于在瀏覽器開發者工具中識別,Worker 線程的控制臺輸出會顯示 在瀏覽器的調試工具中
4、生命周期:Worker 線程會一直運行,直到被顯式終止(worker.terminate() 或 self.close())
5、模塊支持:使用 type: ‘module’ 時,需要確保瀏覽器支持 ES6 模塊
6、資源消耗:創建過多的 Worker 會消耗大量系統資源,應合理控制 Worker 的數量


四、訪問瀏覽器 API

上面章節多次提到了 Worke不能輕易訪問瀏覽器 API,特別是涉及UI操作API幾乎受到限制,對此本小節我們將做一個全面總結歸納哪些api受限制哪些可使用。

Worker無法訪問的瀏覽器 API

1. DOM 操作相關

  • document對象:無法直接操作 HTML 文檔樹
  • window對象:缺少所有與窗口相關的屬性和方法
  • document.querySelector():無法選擇或修改 DOM 元素
  • CSSOM:無法訪問或修改 CSS 樣式

2. 窗口與視圖相關

  • window.innerWidth/innerHeight:無法獲取窗口尺寸
  • scrollTo():無法控制頁面滾動
  • alert()/confirm():無法顯示模態對話框
  • localStorage/sessionStorage:無法直接訪問存儲 API(但可通過IndexedDB操作)

3. 渲染與動畫相關

  • requestAnimationFrame():無法參與主線程渲染循環
  • Canvas 2D 上下文:無法直接繪制(但可通過OffscreenCanvas間接使用)
  • WebGL:無法直接使用(需通過OffscreenCanvas)

4、部分全局對象

  • location對象:僅能訪問有限屬性(如location.origin)
  • history對象:無法操作瀏覽器歷史記錄

Worker 可使用的API

1、數據存儲

  • IndexedDB:支持異步數據庫操作
  • File API:可讀寫文件系統(需用戶交互授權)

2. 網絡請求

  • Fetch API:支持異步網絡請求
  • XMLHttpRequest:與主線程用法一致

3. 定時器

  • setTimeout()/setInterval():基本定時器功能正常使用

4. 多線程協作

  • postMessage():線程間通信核心 API
  • SharedArrayBuffer:支持多線程共享內存

五、構建工具中使用Worker

本章節將講述 Vite、Webpack 4 和 Webpack 5 中 Web Worker 的使用差異及最佳實踐

1、Vite

Vite 從 2.6.0 版本開始內置了對 Web Worker 的支持,無需額外插件即可直接使用,這得益于 ES Module 的動態導入特性

方法1:(添加?worker后綴)

//main.js 主線程
import CalcWorker from './calcWorker.js?worker'; // 關鍵后綴語法
const worker = new CalcWorker();
worker.postMessage({ data:10 });
worker.onmessage = (e) => {console.log('Result:', e.data);
};
//worker.js子線程
import {heavyCalculation} from '../utils/calculation.js'
self.onmessage = (e) => {const result = heavyCalculation(e.data);postMessage(result);};

說明:導入worker文件路徑添加“ ?worker“ 后綴觸發特殊處理,將 worker 文件編譯為獨立 [name].worker.js 的 chunk,自動生成 new Worker(new URL(‘./calcWorker.worker.js’, import.meta.url)) 的現代化語法,開發環境下使用瀏覽器原生 ESM 加載,生產構建為獨立文件。

方法2:(new URL)

//main.js 主線程
const worker = new Worker(new URL("./calcWorker.js", import.meta.url), {type: "module",//啟用模塊化
});
//calcWorker.js子線程
import {heavyCalculation} from '../utils/calculation.js'
self.onmessage = (e) => {const result = heavyCalculation(e.data);postMessage(result);};

說明:自動將 worker 拆分為獨立 chunk,支持 SourceMap,如果worker中使用import導入其他模塊文件,構造函數必須設置type: “module”,開啟對ESM支持

2、Webpack 5

Webpack5 不再需要額外的 loader,通過 new Worker() 即可直接使用,底層依賴于 worker-plugin 的內置支持。

使用方法同vite方法2

//main.js 主線程
const worker = new Worker(new URL('./dataWorker.js', import.meta.url));worker.onmessage = (event) => {console.log('處理結果:', event.data);// 更新UI
};// 發送數據給Worker
worker.postMessage({data: [{ id: 1, value: 5 },{ id: 2, value: 15 },{ id: 3, value: 20 },// 更多數據...]
});
//dataWorker.js子線程
// 模擬大數據處理
self.onmessage = (event) => {const { data } = event.data;// 復雜數據過濾const filteredData = data.filter(item => item.value > 10);self.postMessage(filteredData);
};

說明:Webpack 5內置支持 new Worker() + import.meta.url 規范,自動將 worker 拆分為獨立 chunk,支持 SourceMap,熱更新需要手動配置可通過 experiments.worker: true 開啟

3、Webpack 4

Webpack4 需要借助 worker-loader 來處理 Worker 腳本,該 loader 會將 Worker 腳本打包為可獨立執行的模塊。

(1)安裝依賴

npm install worker-loader --save-dev

(2)配置 webpack.config.js

module.exports = {// 其他配置...module: {rules: [{test: /\.worker\.js$/,use: {loader: 'worker-loader',options: {// 配置 Worker 輸出路徑name: 'workers/[name]-[hash].js'}}}]}
};

(3)頁面使用
方法同Vite 方法1

//main.js 主線程
import MyWorker from '../worker/heavyTask.worker.js';const worker = new MyWorker();// 開始計時
const startTime = Date.now();
worker.postMessage({ startTime });worker.onmessage = (event) => {console.log('計算結果:', event.data.result);console.log(`耗時: ${event.data.duration}ms`);// 更新界面顯示結果
};
//heavyTask.worker.js子線程
self.onmessage = (event) => {// 模擬 CPU 密集型任務let sum = 0;for (let i = 0; i < 100000000; i++) {sum += i;}self.postMessage({ result: sum, duration: Date.now() - event.data.startTime });
};

說明:Webpack4 中建議使用 .worker.js 后綴以便 loader 識別,缺少原生 HMR 支持,修改 worker 需手動刷新


總結

Web Worker 為前端開發者打開了并行計算的大門,通過合理使用可以顯著提升應用性能和用戶體驗。掌握其核心原理、應用模式和性能優化技巧,將使你在構建現代 Web 應用時如虎添翼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86371.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86371.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86371.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

React 18.2.0 源碼打包

一、React源碼地址 GitHub&#xff1a;React 二、參考文章 sourcemap實戰-生成react源碼sourcemap Rollup中文文檔 JavaScript Source Map 詳解 全網最優雅的 React 源碼調試方式 三、打包操作 安裝依賴 // 全局安裝yarn npm i -g yarn // 源碼項目目錄下執行yarn安裝依賴…

UniApp 開發第一個項目

UniApp 開發第一個項目全流程指南,涵蓋環境搭建、項目創建、核心開發到調試發布,結合最新實踐整理而成,適合零基礎快速上手: ?? 一、環境準備(5分鐘) 安裝開發工具 HBuilderX(官方推薦IDE):下載 App 開發版,安裝路徑避免中文或空格 微信開發者工具(調試小程序必備…

Web項目開發中Tomcat10+所需的jar包

版權聲明 本文原創作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 項目背景 Web項目中使用低版本Tomcat時常用的jar包如下&#xff1a; javax.servlet-apijavax.ejb-apijavax.jms-apijavax.json-api 當Web項目使用Tomcat10的版本時&#…

網絡安全就業方向與現實發展分析:機遇、挑戰與未來趨勢

網絡安全行業的戰略地位與就業背景 在數字經濟蓬勃發展的今天&#xff0c;網絡安全已從技術分支演變為關乎國家安全、企業存亡和個人隱私的核心領域。根據國家網信辦數據顯示&#xff0c;2025年我國網絡安全人才缺口達200萬人&#xff0c;較2023年增長33%。這一現象源于三重驅…

iOS runtime隨筆-消息轉發機制

運行時的消息轉發分三步, 當你調用了沒有實現的方法時, 有機會通過runtime的消息轉發機制補救一下 resolveInstanceMethod/resolveClassMethod 這里可以動態去創建方法來解決CrashforwardingTargetForSelector ?????第一步未解決, 就會走到這里, 可以給出一個Target去轉發…

vue3用js+css實現輪播圖(可調整堆疊程度)

先看效果 html <divclass"outer"style"width: 650px;background: #fff;box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);border-radius: 15px;margin: 0 10px 15px 5px;">//這里用的是svg-icon,需要的可自行替換為其他圖片<svg-iconid"btn_l&q…

Three.js項目實戰:從零搭建小米SU7三維汽車

大家如果有過購車的經驗&#xff0c;肯定會先從網站上收集車輛的信息&#xff0c;比如懂車帝&#xff0c;汽車之家&#xff0c;這些網站上逼真的看車效果是如何實現的呢&#xff0c;這節課帶你從0-1快速的手搓一個看車小項目。 懂車帝官網 效果 視頻教程和筆記 大家可以下方小…

Android13 永久關閉SELinux 權限

永久關閉 SeLinux 在cmdline中增加參數androidboot.selinuxpermissive&#xff1b; 芯片: QCM6115 版本: Android 13 kernel: msm-4.19 ~/temp_code/SLM927D_LA.UM.9.15$ git diff device/qcom/bengal/BoardConfig.mk diff --git a/device/qcom/bengal/BoardConfig.mk b…

Linux創建DHCP服務

Linux可作為DHCP服務端使用&#xff0c;為同一個網絡下的其它機器動態分配ip。在一些情況下&#xff0c;可以起到很大的作用。 二級標題 安裝dnsmasq # ubuntu sudo apt update -y sudo apt install -y dnsmasq# centos sudo yum install -y dnsmasq修改配置文件 sudo vim …

汽車4G-TBOX智能終端 汽車國標GB/T 32960協議

汽車國標GB/T 32960協議4G TBOX是一種廣泛應用于車聯網的設備&#xff0c;下面將從不同方面為你詳細介紹。 移動管家汽車4G-TBOX智能終端定義與用途 4G TBOX是基于車聯網技術智能服務系統中的采集終端。以車云網的4G TBOX_CC750為例&#xff0c;它為整個智能服務系統提供GPS/…

JavaEE-Mybatis初階

什么是MyBatis MyBatis是?款優秀的 持久層 框架&#xff0c;?于簡化JDBC的開發。 MyBatis本是 Apache的?個開源項?iBatis&#xff0c;2010年這個項?由apache遷移到了google code&#xff0c;并 且改名為MyBatis 。2013年11?遷移到Github 創建項目時添加依賴 上面有…

記一次jvm機器問題定位經歷

背景 開發過程中發現機器指標異常&#xff0c;端口也hang住無響應&#xff0c;端口返回為timeout&#xff0c;對應探活檢測也失敗了。 現象 在st測試環節&#xff0c;突然每隔一段時間新接口就hang住無響應&#xff0c;觀察機器監控也發現端口探活失敗&#xff0c;看機器指標…

【機器學習深度學習】張量基本操作

目錄 一、張量基本操作 1.1 執行代碼 1.2 運行結果 1.3 代碼解析 ? 1. 創建張量&#xff08;tensor、randn、zeros&#xff09; ? 2. 索引與切片&#xff08;類似 NumPy&#xff09; ? 3. 形狀變換&#xff08;reshape、轉置、壓縮&#xff09; ? 4. 數學運算&#x…

【微信小程序】8、獲取用戶當前的地理位置

1、獲取當前的地理位置 獲取當前的地理位置、速度。當用戶離開小程序后&#xff0c;此接口無法調用。開啟高精度定位&#xff0c;接口耗時會增加&#xff0c;可指定 highAccuracyExpireTime 作為超時時間。 注意&#xff1a; 地圖相關使用的坐標格式應為 gcj02。高頻率調用會…

Jenkins 常用定時構建腳本

Jenkins 常用定時構建腳本 Jenkins 使用 cron 風格的語法來配置定時構建任務&#xff0c;以下是常用的定時構建腳本示例和說明&#xff1a; 基本語法 Jenkins 定時構建使用五個字段表示時間&#xff0c;格式為&#xff1a; MINUTE HOUR DOM MONTH DOWMINUTE - 分鐘 (0-59)H…

ActiveMQ漏洞復現

以下內容均在nextcyber靶場環境中完成&#xff0c;請勿用于非法途徑&#xff01; ActiveMQ 反序列化漏洞&#xff08;CVE-2015-5254&#xff09; Apache ActiveMQ是美國阿帕奇&#xff08;Apache&#xff09;軟件基金會所研發的一套開源的消息中間件&#xff0c;它支持Java消息…

環保處理設備遠程運維管理解決方案

在環保產業蓬勃發展的當下&#xff0c;環保處理設備廠商面臨著愈發激烈的市場競爭。為助力環保處理設備廠商在競爭中脫穎而出&#xff0c;御控工業智能網關打造了一套完善的PLC數據采集設備運維管理平臺解決方案。此方案憑借其獨特優勢&#xff0c;能為環保處理設備廠商帶來顯著…

嵌入式學習筆記DAY43(ARM架構)

一、RAM分類 sram&#xff08;靜態隨機存取存儲器&#xff09;&#xff1a; 原理&#xff1a;使用晶體管來存儲二進制數據0和1&#xff0c;通過雙穩態電路&#xff08;由多個晶體管組成&#xff09;來保持數據狀態&#xff0c;只要持續供電&#xff0c;數據就能穩定保存。數據讀…

2025國際無人機應用及防控大會四大技術專題深度解析

2025國際無人機應用及防控大會四大技術專題深度解析 2025國際無人機應用及防控大會四大技術專題深度解析1 無人機系統技術專題技術特點與應用領域國內領軍企業及案例風險挑戰與發展方向 2 測控與通信導航技術專題技術創新與應用突破領先企業及解決方案現存問題與發展趨勢 3 任務…

DD3118S:USB3.0+Type-c雙頭TF/SD二合一高速0TG多功能手機讀卡器ic

DD3118S封裝是QFN42, GL3224封裝是QFN32 &#xff0c;設計同樣一款3.0讀卡方案&#xff0c;GL3213S需要電容、電阻外圍器件一起要29顆&#xff0c;而DD3118S只需要13顆&#xff0c;方案精簡且設計簡單 DD3118S支持USB3.0Type-c雙頭TF/SD二合一 &#xff0c;高速0TG多功能手機讀…