web worker 是運行在后台的 JavaScript,不會影響頁面的性能。
當在 HTML 頁面中執行腳本時,頁面的狀態是不可響應的,直到腳本已完成。
web worker 是運行在后台的 JavaScript,獨立於其他腳本,不會影響頁面的性能。您可以繼續做任何願意做的事情:點擊、選取內容等等,而此時 web worker 在后台運行。
以上是W3School對WebWorker的定義,講的非常明確。在這段解釋中,我一眼就看到了一句話“執行腳本時,頁面狀態是不可響應的”,這讓我想到了BOM的一些系統對話框,像alert之類的。大家都知道當有alert之類的消息窗口時,它是模態且同步的,整個HTML頁面元素和腳本都會停止無法點擊,直到點擊了確定,腳本才會繼續執行。如果按照HTML5的Web Worker的后台工作的性質,是否意味着可以不受限於對話框的限制,繼續執行代碼。本着實踐出真知,下面一起來看看!
1. 我們首先看看正常情況,一個自動累加器是如何運作的。
第一張圖,附上HTML結構。我們是用一個非常常見的方法,也就是通過一個setTimeout定時器,不斷重復調用自身,達到1S增加一次的效果。然后把累加的值,放到output標簽內。然后我們讓它跑起來吧!
我們可以發現,當我們點擊alert按鈕的時候,數字不再往上累加。這是我們非常常見的啦,因為對話框是同步執行的,意味着不點擊就會造成線程阻塞。難不成用了Web Worker就可以繼續運行?我們接下來繼續看。
2. 使用Web Worker的累加器。
在我們看運行的GIF之前,我們先看看如何構建一個Web Worker。
首先,我們需要檢測一下瀏覽器是否支持Worker,畢竟是一個HTML5的新功能。然后直接通過new一個Worker,再把需要執行的腳本文件作為一個參數傳進去。然后通過監聽這個Web Worker的message事件,數據放在event.data進行實時的反饋。既然有一個message事件,那么那個需要執行的腳本自然會有一個發送message的操作,我們看一下是什么樣子的。
也就是postMessage(data),通過這個API我們可以將Worker里的數據通過message傳出去。然后外部再監聽message事件,進行數據更新。那說了這么多,那真正的問題是否解決了呢?也就是那個,Worker里執行的腳本是獨立於其它腳本,自行在后台運行的。廢話不多說,直接看效果!
非常的牛逼!我忍不住打了幾個字。我們可以清楚的看到,對於單線程的JavaScript來說,即使模態框阻塞了線程,計數器的數字依舊是在做改變的。(這里有些小疑問,既然消息框會讓頁面的腳本停止運行,但是為什么message事件監聽觸發的innerHTML依舊是可以運行?難道事件觸發機制,也可以避免受模態框的影響?有知道的人可以幫忙解答一下,謝謝~!)從這里我們可以明顯看到,確實在web worker的Js腳本是獨立的,並不會和當前頁面的腳本相沖突。當然,這里不得不提一句,Web Worker的Js腳本的作用域和當前頁面Js腳本作用域並不能共享,換言之也就是,它們的全局作用域並不是同一個,Worker的全局作用域是它自己本身,所以Web Worker自然也就無法操作DOM元素。
那我們可以用 Web Worker 做什么呢?因為Js的單線程,我們必須要防止過大的計算堵塞了用戶頁面,那通過這個HTML5最新的 Web Worker 技術,我們可以把一些非常耗時的計算都放在外部,以免影響了用戶體驗。
最后,這里同樣是拋磚引玉。希望可以通過這個可以幫助更多的人,了解到較新的HTML5技術,然后主動的去探尋更多的Web技術。
有同學評論說,Chrome無法通過WebWorker加載本地的Js,這個確實是,本人調試的時候用的是Firefox。但是也是有解決方法的,我們可以通過用Node或者WAMP,快速搭建一個本地服務器,進行WebWorker測試。對於我們勵志的前端工程師來說,用Node搭建簡直飛快啊。這里我就不詳細說了,我再次推薦一個前端工具框架——F.I.S,百度出品。我們通過npm全局裝好后,直接進入demo的文件夾進行一下fis release,然后啟動服務器fis server start。接着我們就可以在瀏覽器通過localhost訪問我們這次的demo了!那我們看一下在Chrome中的運行情況吧。
我們可以看到,Chrome也沒報錯,地址已經換成了本地地址了。但是我們可以看到Chrome下,並沒有Firefox那么酷炫的實時渲染,而是和平常中一樣的停止了。但是當我們點擊確定,計數器已經跳過了許多數字,這說明Web Worker的的確確是獨立於頁面腳本,自己在后台運作的。