天天看點

html5 WebWorkers 防止浏覽器假死

在Web開發的時候經常會遇到浏覽器不響應事件進入假死狀态,甚至彈出“腳本運作時間過長“的提示框,如果出現這種情況說明你的腳本已經失控了。

      一個浏覽器至少存在三個線程:js引擎線程(處理js)、GUI渲染線程(渲染頁面)、浏覽器事件觸發線程(控制互動)。

     1:JavaScript引擎是基于事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來然後加以處理,浏覽器無論再什麼時候都隻有一個JS線程在運作JS程式。

     2:GUI 渲染線程負責渲染浏覽器界面,當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行。但需要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被挂起,GUI更新會被儲存在一個隊列中等到JS引擎空閑時立即被執行。

     3:事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎目前執行的代碼塊如setTimeOut、也可來自浏覽器核心的其他線程如滑鼠點選、AJAX異步請求等,但由于JS的單線程關系所有這些事件都得排隊等待JS引擎處理。

     了解了浏覽器的核心處理方式就不難了解浏覽器為什麼會進入假死狀态了,當一段JS腳本長時間占用着處理機就會挂起浏覽器的GUI更新,而後面的事件響應也被排在隊列中得不到處理,進而造成了浏覽器被鎖定進入假死狀态。另外JS腳本中進行了DOM操作,一旦JS調用結束就會馬上進行一次GUI渲染,然後才開始執行下一個任務,是以JS中大量的DOM操作也會導緻事件響應緩慢甚至真正卡死浏覽器,如在IE6下一次插入大量的HTML。而如果真的彈出了“腳本運作時間過長“的提示框則說明你的JS腳本肯定有死循環或者進行過深的遞歸操作了。

      現在如果遇到了這種情況,我們可以做的不僅僅是優化代碼,html5的webWorkers提供了js的背景處理線程的API,它允許将複雜耗時的單純js邏輯處理放在浏覽器背景線程中進行處理,讓js線程不阻塞UI線程的渲染。這個線程不能和頁面進行互動,如擷取元素、alert等。多個線程間也是可以通過相同的方法進行資料傳遞。

     直接看代碼:

     例子:使用者輸入一個數字,進行加法運算(+=)

     以前的做法:

html5 WebWorkers 防止浏覽器假死
html5 WebWorkers 防止浏覽器假死

    使用webWorkers以後:

    calculate.html

html5 WebWorkers 防止浏覽器假死
html5 WebWorkers 防止浏覽器假死

      calculate.js

html5 WebWorkers 防止浏覽器假死
html5 WebWorkers 防止浏覽器假死

     對比上面的兩種實作方式,當計算值達到100億的時候,普通做法耗時已經很長,且一般會卡死了。

html5 WebWorkers 防止浏覽器假死

     webWorkers在Chrome15下的效果。 更正:getTime()傳回的應該是毫秒(ms),而不是秒(s)。

html5 WebWorkers 防止浏覽器假死

      普通方法在Chrome15下的效果

     可見webWorkers在未來的web應用中還是非常有價值的。

繼續閱讀