Worker在JavaScript中發揮了什麼作用?

2020-12-11 讀芯術

全文共2548字,預計學習時長8分鐘

多年以來,JavaScript最麻煩的特徵之一就是,如果某個任務耗時太長,剩下的代碼就會遇到阻塞而無法運行。

JavaScript是單線程的程式語言,這一特點導致用戶需要等待代碼按照順序運行。

但事實上有一種方式可以避免這種困境,它就是Worker。

在本文中,小芯將介紹Worker的使用方式。

閱讀之前

讀者需要知道JavaScript是一種單線程語言。

同步編碼

先來看看讀者可能已經熟知的JavaScript代碼樣式

let cnt = 0;

for (let i = 0; i < 10e8; i += 1) {

cnt += 1;

}

console.log(cnt);

在這段代碼的for循環中,cnt每次增加1,總共增加了次。而console.log要等到for循環結束後才能執行。

在Chrome瀏覽器控制臺中,這需要花費很長時間。

這段代碼需要耗費將近3秒。

無論如何,直到for循環結束cnt才會列印出來。

許多開發者都被這個問題困擾,因為用戶必須等待當前執行的任務完成。

異步代碼

JavaScript的設計者為開發者提供了不會阻塞程序流的特殊函數。這些函數處於和普通任務不同的等待隊列中。一般而言,它們可以在所有普通程序執行之後再執行。這些任務被稱為異步任務。

let cnt = 0;

setTimeout(() => {

for (let i = 0; i < 10e8; i += 1) {

cnt += 1;

}

console.log(cnt);

});

console.log(cnt);

這段代碼的運行結果和前面一段有所不同。

但仍然需要等待較長的時間。

這裡的for循環包含在 setTimeout中. setTimeout中的代碼會等待所有普通任務完成後再執行。

但這並非解決代碼流堵塞問題的最佳方案。雖然 setTimeout是一個不阻礙正常代碼流的異步函數,但是這樣做僅僅改變了函數的執行順序。

let cnt = 0;

setTimeout(() => {

for (let i = 0; i < 10e8; i += 1) {

cnt += 1;

}

console.log(cnt);

});

setTimeout(() => {

console.log(cnt);

});

console.log(cnt);

看看這個例子,其中使用了另一個setTimeout,它包含一個立即列印cnt的函數。然而第二個setTimeout總是在第一個setTimeout結束for循環後才開始運行console.log(cnt)指令。如果第一個setTimeout包含的任務耗時較長,那麼第二個setTimeout將無法運行。

為什麼?因為Javascript是一種單線程程式語言。異步函數存在於不同的任務隊列中,但它們仍然遵循單線程規則。

Workers

Web Worker是一種網絡接口,這意味著它無法訪問或管理文檔對象模型。Worker存在於一個不同的線程中,它和主線程互不幹擾。它在一個新的Worker對象創建時接受信息,然後向worker發送信息。

let worker;

if ('Worker' in window) {

worker = new Worker('file_name');

}

創建新的Worker實例十分簡單。new Worker這條指令接受一個字符串或者超連結作為參數。這個參數的格式一般如下所示:

new Worker('/worker.js');

實例創建之後,可以向另一個線程發送信息。

worker.postMessage('From Main Thread');

於是可以在worker所處的線程中收到這個信息。

// worker.jsthis.addEventListener('message', event => {

console.log(event.data);

});

Worker成功接受信息。

如果仔細查看日誌,會發現文件名是worker.js而不是main.js或者app.js。這說明worker接受了完好的信息。

現在,讓worker在收到主線程信息的同時也向主線程發送一條信息。

// main.js

worker.addEventListener('message', event => {

console.log(event.data);

});// worker.js

this.addEventListener('message', event => {

...

this.postMessage('From Worker Thread');

});

這段代碼看起來有些冗餘。讀者將會看到其工作流,但是首先來看看結果。

現在能看到兩條信息。

這段代碼是如何工作的呢?

onMessage代表從線程另一端接受信息這一事件,postMessage則代表向線程另一端發送信息這一事件。

代碼測試

在這個測試中可以看到兩點。

· For循環的運行總時長

· 代碼阻斷

這個示例使用React製作。狀態消息應該按照預期列印,然而同步和異步行為不會列印除了總運行時長外的任何信息。因為在React中,狀態改變也是一種異步行為,需要等待普通任務和其他前序異步任務完成才能執行。

另一方面,worker不需要等待,因為它位於另一個線程中。For循環在worker線程中,異步任務則在主線程中,所以它們不會互相打斷。

結論

通常worker被用於佔用大量CPU資源的程序中,比如2D canvas 和矢量圖。因為worker位於另一個線程中,它不會阻斷主線程中的任何任務,比如UI渲染。如果能將worker運用自如,它的效果將十分強大。包括IE10在內的眾多瀏覽器都能夠很好地支持這一功能。

留言點讚關注

我們一起分享AI學習與發展的乾貨

如轉載,請後臺留言,遵守轉載規範

相關焦點

  • WebWorker 在文本標註中的應用
    中進行,以保證主線程中用戶流暢的地圖交互(縮放、平移、旋轉)。/worker/worker';// 主線程初始化initWorker() { this.worker = new Worker(); this.worker.addEventListener('message', this.handleWorkerMessage); // 通知 Worker 請求 GeoJSON 數據並創建數據瓦片索引
  • JavaScript是什麼
    javaScript的簡單介紹【javaScript是什麼?】javaScript----是一種面向對象的腳本語言。面向對象是一種編程思想,看不見摸不著,只能體會,用實際行動來證明。面向對象這種編程思想是對面向過程的思想的升華。
  • HTML,CSS,Javascript在Web開發中分別起什麼作用?
    1、什麼是HTML(超文本標記語言 Hyper Text Markup Language),HTML 是用來描述網頁的一種語言。>3、JavaScript是一種腳本語言,其原始碼在發往客戶端運行之前不需經過編譯,而是將文本格式的字符代碼發送給瀏覽器由瀏覽器解釋運行對於一個網頁,HTML定義網頁的結構,CSS描述網頁的樣子,JavaScript設置一個很經典的例子是說HTML就像 一個人的骨骼、器官,而CSS就是人的皮膚,有了這兩樣也就構成了一個植物人了,加上javascript
  • JavaScript為什麼這麼難?
    javascript中的this不是靜態綁定的,而是動態綁定的。而且可以人為改變指向。看看下面這個例子控制臺將輸出什麼?javascript中的作用域是可以通過向上查找的,通過閉包可以讓函數引用底層的作用域變量,可以在高層訪問底層的作用域。好象沒什麼難得。看看例子
  • Service Workers - JavaScript API 簡介
    本文已經原作者 Felix Gerschau 授權翻譯service worker 是什麼Service Worker 是 Chrome 團隊提出和力推的一個Service Worker 最主要的特點是:在頁面中註冊並安裝成功後,運行於瀏覽器後臺,不受頁面刷新的影響,可以監聽和截攔作用域範圍內所有頁面的 HTTP 請求。
  • Web Worker 文獻綜述
    但多個並行的線程共享內存, 會產生競爭問題(Race Conditions).可以參考微軟官方文檔[37], 具體步驟為:按 F12 打開調試工具, 在 Script Panel 中, 開始是看不到 Worker 線程源碼的, 點擊 Start debugging, 就能看到 Worker 線程的 alloy-worker.js 源碼.
  • 離婚糾紛中,律師能發揮什麼作用?
    如果就法律層面來講,離婚糾紛中,律師能發揮什麼作用呢?離婚中涉及很多法律專業知識,當事人缺乏全面的法律知識,離婚律師在此中發揮的作用是為當事人解答法律問題,給當事人提供有利的幫助。二、梳理案件。為什麼很多人離婚訴訟都要找律師代理?當事人不懂法律是一方面,另一方面是當事人無法正確梳理案件、基本案情思路、分析案件突破口等問題,能清楚的讓當事人表述自己的訴求。
  • JavaScript中的陷阱大集合
    evaleval 可以將字符串以javascript代碼的形式來解析執行,但是一般來說我們不建議這麼做。因為eval非常慢 - 當javascript被加載到瀏覽器中時,它會被編譯成本地代碼;然而執行的過程中每次遇到eval表達式,編譯引擎都將重新啟動執行編譯,這樣做的代 價太大了。
  • 在javascript程式語言中,數據類型boolean的應用場景
    在javascript編程中,數據類型布爾是最常見的一種類型。此種類型邏輯上比較簡單,只有兩個值:true和false。布爾數據類型與計算機底層的電路開與關有著密切的關聯。但是,布爾值true不一定是1,false不一定是0。
  • Javascript 生成器
    什麼是生成器?Javascript 的生成器語法類似於 PHP,但是區別也很大,如果你希望它們的作用相同,那麼最終你會感到非常困惑。 在 javascript 中,如果想要使用生成器,則需要: 定義特殊的生成器函數 調用該函數創建一個生成器對象 在循環中使用該生成器對象,或直接調用其 方法 我們以下面這個簡單的程序做為起點,並執行以下每個步驟:
  • web worker的介紹和使用
    簡介什麼是web worker呢?從名字上就可以看出,web worker就是在web應用程式中使用的worker。
  • 每日一課 | JavaScript中的數組
    JavaScript中的數組具有length屬性,該屬性返回該數組的大小。我們僅初始化數組,並且未在數組中添加任何元素。如何檢索數組中的第一個和最後一個元素? 在javascript中,數組不是其他語言(例如c#,java)的定長數組類型,即使它們聲明為定長,它也會動態增長。
  • BBC地道英語|White collar worker / blue-collar worker 白領/藍領
    Well, looking at our clothes, you are a T-shirt-no-collar worker and I’m a yellow-with-polka-dot-collar worker.How about that?嗯,看我們的衣服,你是T恤無領工作者,我是黃色帶圓點領子的工作者。你認為這個回答怎麼樣?
  • JavaScript 中 Eval 函數的前世今生,執行代碼字符串
    我們在 ["new Function" 語法](https://zh.javascript.info/new-function ""new Function" 語法") 一章中對 new Function 構造器進行了詳細說明。
  • 如何在javascript中創建一個對象?
    javascript是一門基於對象而不是面向對象的語言,由於它的這個缺陷,在javascript中實現面向對象時十分彆扭,就比如創建對象,由於在ES6之前沒有class關鍵字,想要創建對象必須依賴以下幾種間接方式。
  • 七天學會javascript第一天javascript介紹
    javascript介紹javascript數據類型javascript運算符javascript對象javascriptDate對象javascript String對象JavaScript常用於實現一些前端效果。
  • JavaScript入門教程
    起源javascript前身叫做livescript,sun公司推出java,netspace公司引進java的概念,重新設計livescript,並更名javascript。發明者,布蘭登.艾克,表單驗證原先要經過伺服器,伺服器壓力大,等待時間長,js僅在客戶端就可完成。是什麼是一種腳本語言,是一種輕量級的程式語言。
  • 重新認識javascript的settimeout和異步
    但是原因到底是什麼呢?自己一時也說不太清楚,反正感覺就是一個死循環造成的。然後看了一下文章下面的評論,發現5樓和6樓的回答很有道理,主要意思就是說javascript引擎是單線程執行的,while循環那裡執行的時候,settimeout裡面的函數根本沒有執行的機會,這樣while那裡永遠為真,造成死循環。
  • 【光明論壇】在幹事創業中發揮合格作用
    要抓住「關鍵少數」,抓實基層支部,堅持問題導向,發揮先進典型示範作用。要落實各級黨委(黨組)主體責任,落實好「兩學一做」學習教育常態化制度化各項舉措,保證黨的組織履行職能、發揮核心作用,保證領導幹部忠誠乾淨擔當、發揮表率作用,保證廣大黨員以身作則、發揮先鋒模範作用,為統籌推進「五位一體」總體布局和協調推進「四個全面」戰略布局提供堅強組織保證。
  • 網頁技巧:妥善處理JavaScript中的錯誤
    在這些實例中,JavaScript語言使得發現錯誤變得簡單,從而能夠繼續下去。發現錯誤和Java、C#等其他語言相類似,JavaScript中包括了try/catch/finally語句。一個try語句包含了一組代碼,在這組代碼中,像運行時間錯誤這樣的異常可能會發生。