前端 Web Workers 簡介

簡介

以前我們總說,JS 是單線程沒有多線程,當 JS 在頁面中運行長耗時同步任務的時候就會導致頁面假死影響用戶體驗,從而需要設置把任務放在任務隊列中;執行任務隊列中的任務也并非多線程進行的,然而現在 HTML5 提供了我們前端開發這樣的能力 - Web Workers API,我們一起來看一看 Web Worker 是什么,怎么去使用它,在實際生產中如何去用它來進行產出。

概述

Web Workers 使得一個 Web 應用程序可以在與主執行線程分離的后臺線程中運行一個腳本操作。這樣做的好處是可以在一個單獨的線程中執行費時的處理任務,從而允許主(通常是 UI)線程運行而不被阻塞。

它的作用就是給 JS 創造多線程運行環境,允許主線程創建 worker 線程,分配任務給后者,主線程運行的同時 worker 線程也在運行,相互不干擾,在 worker 線程運行結束后把結果返回給主線程。這樣做的好處是主線程可以把計算密集型或高延遲的任務交給 worker 線程執行,這樣主線程就會變得輕松,不會被阻塞或拖慢。這并不意味著 JS 語言本身支持了多線程能力,而是瀏覽器作為宿主環境提供了 JS 一個多線程運行的環境。

不過因為 worker 一旦新建,就會一直運行,不會被主線程的活動打斷,這樣有利于隨時響應主線程的通性,但是也會造成資源的浪費,所以不應過度使用,用完注意關閉。或者說:如果 worker 無實例引用,該 worker 空閑后立即會被關閉;如果 worker 實列引用不為 0,該 worker 空閑也不會被關閉。

兼容性

在這里插入圖片描述

注意事項

worker 線程的使用有一些注意點:

  1. 同源限制 worker 線程執行的腳本文件必須和主線程的腳本文件同源,這是當然的了,總不能允許 worker 線程到別人電腦上到處讀文件吧
  2. 文件限制 為了安全,worker 線程無法讀取本地文件,它所加載的腳本必須來自網絡,且需要與主線程的腳本同源
  3. DOM 操作限制 worker 線程在與主線程的 window 不同的另一個全局上下文中運行,其中無法讀取主線程所在網頁的 DOM 對象,也不能獲取 document、window等對象,但是可以獲取navigator、location(只讀)、XMLHttpRequest、setTimeout族等瀏覽器API
  4. 通信限制 worker 線程與主線程不在同一個上下文,不能直接通信,需要通過postMessage方法來通信
    腳本限制 worker 線程不能執行alert、confirm,但可以使用 XMLHttpRequest 對象發出 ajax 請求

示例

在主線程中生成 Worker 線程很容易:

var myWorker = new Worker(jsUrl, options)

Worker() 構造函數,第一個參數是腳本的網址(必須遵守同源政策),該參數是必需的,且只能加載 JS 腳本,否則報錯。第二個參數是配置對象,該對象可選。它的一個作用就是指定 Worker 的名稱,用來區分多個 Worker 線程。

// 主線程var myWorker = new Worker('worker.js', { name : 'myWorker' });// Worker 線程
self.name // myWorker

關于 api 什么的,直接上例子大概就能明白了,首先是 worker 線程的 js 文件:

workerThread1.js 文件中

關于 api 什么的,直接上例子大概就能明白了,首先是 worker 線程的 js 文件:// workerThread1.jslet i = 1function simpleCount() {i++self.postMessage(i)setTimeout(simpleCount, 1000)
}simpleCount()self.onmessage = ev => {postMessage(ev.data + ' 呵呵~')
}

在 HTML 文件中的 body 中:

HTML 文件中的 body 中:<!--主線程,HTML文件的body標簽中--><div>Worker 輸出內容:<span id='app'></span><input type='text' title='' id='msg'><button onclick='sendMessage()'>發送</button><button onclick='stopWorker()'>stop!</button>
</div><script type='text/javascript'>if (typeof(Worker) === 'undefined')	// 使用Worker前檢查一下瀏覽器是否支持document.writeln(' Sorry! No Web Worker support.. ')else {window.w = new Worker('workerThread1.js')window.w.onmessage = ev => {document.getElementById('app').innerHTML = ev.data}window.w.onerror = err => {w.terminate()console.log(error.filename, error.lineno, error.message) // 發生錯誤的文件名、行號、錯誤內容}function sendMessage() {const msg = document.getElementById('msg')window.w.postMessage(msg.value)}function stopWorker() {window.w.terminate()}}
</script>

api

主線程中的api,worker表示是 Worker 的實例:

  • worker.postMessage: 主線程往 worker 線程發消息,消息可以是任意類型數據,包括二進制數據
  • worker.terminate: 主線程關閉 worker 線程
  • worker.onmessage: 指定 worker 線程發消息時的回調,也可以通過worker.addEventListener(‘message’,cb)的方式
  • worker.onerror: 指定 worker 線程發生錯誤時的回調,也可以 worker.addEventListener(‘error’,cb)

Worker 線程中全局對象為 self,代表子線程自身,這時 this指向self,其上有一些 api:

  • self.postMessage: worker 線程往主線程發消息,消息可以是任意類型數據,包括二進制數據
  • self.close: worker 線程關閉自己
  • self.onmessage: 指定主線程發 worker 線程消息時的回調,也可以self.addEventListener(‘message’,cb)
  • self.onerror: 指定 worker 線程發生錯誤時的回調,也可以 self.addEventListener(‘error’,cb)

注意,w.postMessage(aMessage, transferList) 方法接受兩個參數,aMessage 是可以傳遞任何類型數據的,包括對象,這種通信是拷貝關系,即是傳值而不是傳址,Worker 對通信內容的修改,不會影響到主線程。事實上,瀏覽器內部的運行機制是,先將通信內容串行化,然后把串行化后的字符串發給 Worker,后者再將它還原。一個可選的 Transferable 對象的數組,用于傳遞所有權。如果一個對象的所有權被轉移,在發送它的上下文中將變為不可用(中止),并且只有在它被發送到的 worker 中可用。可轉移對象是如 ArrayBuffer,MessagePort 或 ImageBitmap 的實例對象,transferList數組中不可傳入 null。

worker 線程中加載腳本的 api:

importScripts('script1.js')	// 加載單個腳本
importScripts('script1.js', 'script2.js')	// 加載多個腳本

使用場景

個人覺得,Web Worker 我們可以當做計算器來用,需要用的時候掏出來摁一摁,不用的時候一定要收起來。

加密數據 有些加解密的算法比較復雜,或者在加解密很多數據的時候,這會非常耗費計算資源,導致 UI 線程無響應,因此這是使用 Web Worker 的好時機,使用 Worker 線程可以讓用戶更加無縫的操作 UI。

預取數據 有時候為了提升數據加載速度,可以提前使用 Worker 線程獲取數據,因為 Worker 線程是可以是用 XMLHttpRequest 的。

預渲染 在某些渲染場景下,比如渲染復雜的 canvas 的時候需要計算的效果比如反射、折射、光影、材料等,這些計算的邏輯可以使用 Worker 線程來執行,也可以使用多個 Worker 線。

復雜數據處理場景 某些檢索、排序、過濾、分析會非常耗費時間,這時可以使用 Web Worker 來進行,不占用主線程。

預加載圖片 有時候一個頁面有很多圖片,或者有幾個很大的圖片的時候,如果業務限制不考慮懶加載,也可以使用 Web Worker 來加載圖片,可以參考一下這篇文章的探索這篇文章的探索,這里簡單提要一下。

// 主線程
let w = new Worker("js/workers.js");
w.onmessage = function (event) {var img = document.createElement("img");img.src = window.URL.createObjectURL(event.data);document.querySelector('#result').appendChild(img)
}// worker線程
let arr = [...好多圖片路徑];
for (let i = 0, len = arr.length; i < len; i++) {let req = new XMLHttpRequest();req.open('GET', arr[i], true);req.responseType = "blob";req.setRequestHeader("client_type", "DESKTOP_WEB");req.onreadystatechange = () => {if (req.readyState == 4) {postMessage(req.response);}}req.send(null);
}

在實戰的時候注意

  1. 雖然使用 worker 線程不會占用主線程,但是啟動 worker 會比較耗費資源
  2. 主線程中使用 XMLHttpRequest 在請求過程中瀏覽器另開了一個異步 http 請求線程,但是交互過程中還是要消耗主線程資源

在 Webpack 項目里面使用 Web Worker 請參照:怎么在 ES6+Webpack 下使用 Web Worker

參考文章

mdn

前端 Web Workers 到底是什么

Web Worker在項目中的妙用

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

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

相關文章

App備案、ios備案Bundle ID查詢、公鑰信息、SHA-1值

App備案、ios備案Bundle ID查詢、公鑰信息、SHA-1值 Bundle ID這個就不說了&#xff0c;都知道是啥&#xff0c;主要說公鑰信息和SHA-1值的獲取 打開鑰匙串訪問&#xff0c;找到當前需要備案App的dis證書&#xff0c;如下&#xff1a; #####右鍵點擊顯示簡介 #####可以看…

03.仿簡道云公式函數實戰-QLExpress初探

1. 前言 在上一篇文章中&#xff0c;我們簡單介紹了一下表達式引擎&#xff0c;并引出我們的主角QLExpress.在這篇文章中&#xff0c;我們先來一個QLExpress的熱身。 2. 初探QLExpress 源碼地址&#xff1a;https://github.com/alibaba/qlExpress 筆者下載源碼的版本是3.3.…

STL源碼剖析筆記——適配器(adapters)

系列文章目錄 STL源碼剖析筆記——迭代器 STL源碼剖析筆記——vector STL源碼剖析筆記——list STL源碼剖析筆記——deque、stack&#xff0c;queue STL源碼剖析筆記——Binary Heap、priority_queue STL源碼剖析筆記——AVL-tree、RB-tree、set、map、mutiset、mutimap STL源…

【Spring 基礎】00 入門指南

【Spring 基礎】00 入門指南 文章目錄 【Spring 基礎】00 入門指南1.簡介2.概念1&#xff09;控制反轉&#xff08;IoC&#xff09;2&#xff09;依賴注入&#xff08;DI&#xff09; 3.核心模塊1&#xff09;Spring Core2&#xff09;Spring AOP3&#xff09;Spring MVC4&…

php實現截取姓名中的第一個字作為頭像的實戰記錄

php 截取中文字符串第一個字 substr 函數 在 PHP 中&#xff0c;使用 substr 函數來截取中文字符串的第一個字。由于 PHP 默認的字符編碼是 UTF-8&#xff0c;它可以正確處理中文字符。 $chineseString "你好世界"; $firstChar substr($chineseString, 0, 1); e…

vue2 組件內路由守衛使用

1、beforeRouteEnter 進入頁面 to – 即將要跳轉到的頁面 form – 跳轉前的頁面&#xff0c;從哪個頁面跳轉過來的 next – 下一步&#xff0c;若無指定跳轉的路由&#xff0c;設置為空 next() 即可 beforeRouteEnter(to, from, next) {next() }, 使用 beforeRouteEnter 時&…

中文分詞演進(查詞典,hmm標注,無監督統計)新詞發現

查詞典和字標注 目前中文分詞主要有兩種思路&#xff1a;查詞典和字標注。 首先&#xff0c;查詞典的方法有&#xff1a;機械的最大匹配法、最少詞數法&#xff0c;以及基于有向無環圖的最大概率組合&#xff0c;還有基于語言模型的最大概率組合&#xff0c;等等。 查詞典的方法…

知識產權服務企業網站建設效果如何

知識產權服務也有較高的市場需求度&#xff0c;尤其如今互聯網深入到各個行業&#xff0c;無論個人還是企業都會以不同的方式經營&#xff0c;相應的為保障自身權益&#xff0c;注冊商標、專利等自然不可少&#xff0c;而對普通小白來說&#xff0c;想要完成這些流程也是有些難…

Python實現獲取b站視頻的彈幕內容

前言 本文是該專欄的第39篇,后面會持續分享python的各種干貨知識,值得關注。 在本專欄之前,有詳細介紹使用python增加b站視頻的播放量方法,感興趣的同學可往前翻閱《Python-增加b站視頻播放量》。而本文,筆者再來單獨的詳細介紹,通過python來獲取b站視頻的彈幕內容。如下…

CGAL的3D皮膚表面網格

1、介紹 Edelsbrunner 引入的皮膚表面和具有豐富而簡單的組合和幾何結構&#xff0c;使其適合在生物計算中模擬大分子。 對這些表面進行網格劃分通常是進一步處理其幾何形狀所必需的&#xff0c;例如在數值模擬和可視化中。 皮膚表面由一組加權點&#xff08;輸入球&#xff09…

力扣labuladong——一刷day70

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、力扣814. 二叉樹剪枝二、力扣1325. 刪除給定值的葉子節點 前言 這道題的難點在于要一直剪枝&#xff0c;直到沒有值為 0 的葉子節點為止&#xff0c;只有從…

RecursionError: maximum recursion depth exceeded in comparison

諸神緘默不語-個人CSDN博文目錄 這個bug的產生原因是運行rouge包時句子太長&#xff0c;所以遞歸次數過多了。完整的報錯信息懶得粘了&#xff0c;總之很長&#xff0c;解決方案就是手動在程序開始處就增大遞歸次數&#xff1a; import sys sys.setrecursionlimit(100000)具體…

html通過CDN引入Vue使用Vuex以及Computed、Watch監聽

html通過CDN引入Vue使用Vuex以及Computed、Watch監聽 近期遇到個需求&#xff0c;就是需要在.net MVC的項目中&#xff0c;對已有的項目的首頁進行優化&#xff0c;也就是寫原生html和js。但是咱是一個寫前端的&#xff0c;寫html還可以&#xff0c;.net的話&#xff0c;開發也…

K8S學習指南-minikube的安裝

簡介 Minikube 是一個用于在本地開發環境中運行 Kubernetes 集群的工具。它允許開發人員在單個節點上體驗 Kubernetes&#xff0c;無需配置復雜的生產環境。本指南將詳細介紹在 Windows、CentOS 和 Ubuntu 系統上安裝 Minikube 的步驟。 1. Windows 系統安裝 1.1 &#xff1…

期末速成數據庫極簡版【查詢】(3)

目錄 多表查詢 【8】多表連接——內連接 &#x1f642;等值連接 &#x1f642;自然連接 &#x1f642;非等值連接 【9】多表連接——外連接 【10】交叉連接不考 【11】聯合查詢 【12】擴展多表連接 【13】嵌套查詢 &#x1f642; 多表查詢 【8】多表連接——內連…

HIVE學習(hive基礎)

HIVE基礎介紹 一、HIVE簡介二、hive的數據類型1、基本數據類型2、復合數據類型 三、HIVE的DDL操作四、創建一個表1. 建表語句 五、修改表結構1.修改表名2. 列修改或增加3. 修改分區 五、常見函數六、一對一關聯left join左關聯right join 右關聯內連接全連接查詢只有A表的數據 …

計算機視覺-機器學習-人工智能頂會 會議地址

計算機視覺-機器學習-人工智能頂會 會議地址 最近應該要整理中文資料的參考文獻&#xff0c;很多會議文獻都需要補全會議地點&#xff08;新國標要求&#xff09;。四處百度感覺也挺麻煩的&#xff0c;而且沒有比較齊全的網站可以搜索。因此自己整理了一下計算機視覺-機器學習…

OSPF路由協議

隨著Internet技術在全球范圍的飛速發展&#xff0c;OSPF已成為目前應用最廣泛的路由協議之一。OSPF&#xff08;Open Shortest Path First&#xff09;路由協議是由IETF&#xff08;Internet Engineering Task Force&#xff09;IGP工作組提出的&#xff0c;是一種基于SPF算法的…

JS 云服務 Deno Depoly 宣布,推出定時運行功能 Deno Cron

如果需要定時執行 JS 腳本&#xff0c;以后多一個選項。 Web 構建日益復雜。編寫現代軟件包括利用云基礎設施、剖析模板代碼和管理復雜的配置&#xff0c;而開發人員只想專注于編寫業務邏輯。 Deno 旨在通過刪除配置和不必要的模板&#xff0c;從根本上簡化 Web 開發。我們將無…

網絡攻擊(三)--攻擊階段

5. 威脅建模階段 目標 了解威脅建模階段的工作內容 工作內容 威脅建模主要使用在情報搜集階段所獲取到的信息&#xff0c;來標識出目標系統上可能存在的安全漏洞與弱點。 在進行威脅建模時&#xff0c;確定最為高效的攻擊方法、所需要進一步獲取到的信息&#xff0c;以及從…