關於Web Worker你必須知道的7件事

介紹

經過使用Web Worker, 咱們能夠在瀏覽器後臺運行Javascript, 而不佔用瀏覽器自身線程。Web Worker能夠提升應用的整體性能,而且提高用戶體驗。若是你想在本身的Web應用中使用Web Worker, 不妨來了解一下有關Web Worker的7件事。javascript

1. Web Worker 可讓你在後臺運行Javascript

通常來講Javascript和頁面的UI會共用一個線程,因此當點擊一個按鈕開始運行Javascript後,在這段代碼運行完畢以前,頁面是沒法響應用戶操做的,換句話來講就是被「凍結」了。而這段代碼能夠交給Web Worker在後臺運行,那麼頁面在Javascript運行期間依然能夠響應用戶操做。後臺會啓動一個worker線程來執行這段代碼,用戶能夠建立多個worker線程。因此你能夠在前臺作一些小規模分佈式計算之類的工做,不過Web Worker有如下一些使用限制:html

 

  • Web Worker沒法訪問DOM節點;
  • Web Worker沒法訪問全局變量或是全局函數;
  • Web Worker沒法調用alert()或者confirm之類的函數;
  • Web Worker沒法訪問window、document之類的瀏覽器全局變量;

 

不過Web Worker中的Javascript依然可使用setTimeout(),setInterval()之類的函數,也可使用XMLHttpRequest對象來作Ajax通訊。java

2. 有兩種Web Worker

Web workers可分爲兩種類型:專用線程dedicated web worker,以及共享線程shared web worker。 Dedicated web worker隨當前頁面的關閉而結束;這意味着Dedicated web worker只能被建立它的頁面訪問。與之相對應的Shared web worker能夠被多個頁面訪問。在Javascript代碼中,「Work」類型表明Dedicated web worker,而「SharedWorker」類型表明Shared web worker。jquery

在絕大多數狀況下,使用Dedicated web worker就足夠了,由於通常來講在web worker中運行的代碼是專爲當前頁面服務的。而在一些特定狀況下,web worker可能運行的是更爲廣泛性的代碼,能夠爲多個頁面服務。在這種狀況下,咱們會建立一個共享線程的Shared web worker,它能夠被與之相關聯的多個頁面訪問,只有當全部關聯的的頁面都關閉的時候,該Shared web worker纔會結束。相對Dedicated web worker,shared web worker稍微複雜些。web

3. 「Worker」對象表明Dedicated Web Worker

如今來看如何使用Dedicated web worker。下面的例子中用到了jQuery以及Modernizr做爲Javascript庫,而後往HTML頁面中加入如下代碼:數據庫

 

[html]  view plain copy
 
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <title></title>  
  5. <script type="text/javascript" src="script/modernizr.js"></script>  
  6. <script type="text/javascript" src="script/jquery-2.0.0.js"></script>  
  7. <script type="text/javascript">  
  8. $(document).ready(function(){  
  9. if(!Modernizr.webworker){  
  10. alert("This browser doesn't support Web Worker!");  
  11. return;  
  12. }  
  13. $("#btnStart").click(function(){  
  14. var worker = new Worker("script/lengthytask.js");  
  15. worker.addEventListener("message", function(evt){  
  16. alert(evt.data);  
  17. }, false);  
  18. worker.postMessage(10000)  
  19. });  
  20. });  
  21. </script>  
  22. </head>  
  23. <body>  
  24. <form>  
  25. <input type="button" id="btnStart" value="Start Processing"/>  
  26. </form>  
  27. </body>  
  28. </html>  

 

這個HTML頁面中有個按鈕,點擊後會運行一個Javascript文件。上面的代碼中首先檢測當前瀏覽器是否支持Web Worker,不支持的話,就跳出提醒信息。瀏覽器

按鈕的點擊事件中建立了Worker對象,並給它指定了Javascript腳本文件——lengthytask.js(稍後會有代碼),而且給Worker對象綁定了一個「message」事件。該事件會在後臺代碼(lengthytask.js)向頁面返回數據時觸發。「message」事件能夠經過event.data來獲取後臺代碼傳回的數據。最後,postMessage方法正式執行lengthytask.js,該方法還能夠向後臺代碼傳遞參數, 後臺代碼一樣經過message事件獲取該參數。服務器

下面是lengthytask.js主要包含的代碼:asp.net

 

[javascript]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. addEventListener("message", function(evt){  
  2. var date = new Date();  
  3. var currentDate = null;  
  4. do {  
  5. currentDate = new Date();  
  6. }while(currentDate - date < evt.data);  
  7. postMessage(currentDate);  
  8. }, false);  


以上代碼在後臺監聽message時間,並獲取頁面傳來的參數:10000;這裏其實是一個計時函數:在message事件被觸發10000毫秒以後,把結果(currentDate)傳給頁面。分佈式

 

因此當點擊「Start Processing」按鈕,頁面會在10秒鐘後把當時的時刻alert出來。在這10秒鐘內頁面依然能夠響應鼠標鍵盤事件。

4. 「SharedWorker」對象表明Shared Web Worker

前面的代碼使用的是dedicated web worker。 這一節會用shared web worker代替dedicated web worker,來區別二者的不一樣。下面是同一個例子的shared web worker版本:

 

[javascript]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. addEventListener("message", function(evt){  
  2. var date = new Date();  
  3. var currentDate = null;  
  4. do {  
  5. currentDate = new Date();  
  6. }while(currentDate - date < evt.data);  
  7. postMessage(currentDate);  
  8. }, false);  

請注意加黑的代碼,這裏建立了一個SharedWorker對象,並把message事件綁定在shared worker的port對象上;一樣由port對象發起postMessage, 開始執行後臺代碼sharedlengthytask.js。

下面是sharedlengthytask.js的主要代碼:

 

[javascript]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. var port;  
  2. addEventListener("connect", function(evt){  
  3. port = evt.ports[0];  
  4. port.addEventListener("message", function(evt){  
  5. var date = new Date();  
  6. var currentDate = null;  
  7. do {  
  8. currentDate = new Date();  
  9. }while(currentDate - date < evt.data);  
  10. port.postMessage(currentDate);  
  11. }, false);  
  12. port.start();  
  13. }, false);  


使用SharedWorker對象的後臺代碼須要綁定connect和message事件, connect事件會在頁面上的port被start時觸發。以後的message事件的回調函數與以前的基本相同,最後port調用postMessage方法把結果傳回給頁面。

 

5. Web Worker使用XMLHttpRequest與服務端通訊

有些狀況下,web worker還須要與服務器進行交互。好比頁面可能須要處理來自數據庫中的信息,咱們就須要使用Ajax技術與服務器交互,下面代碼包含了web worker如何從服務端獲取數據:

 

[javascript]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. addEventListener("message", function(evt){  
  2. var xhr = new XMLHttpRequest();  
  3. xhr.open("GET", "lengthytaskhandler.ashx");  
  4. xhr.onload = function(){  
  5. postMessage(xhr.responseText);  
  6. };  
  7. xhr.send();  
  8. },false);  


上面的代碼向服務端的asp.net服務lengthytaskhandler.ashx發出GET請求。並註冊了獲取數據後的onload事件。下面的代碼是服務端的lengthytaskhandler.ashx:

 

 

[csharp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. namespace WebWorkerDemo  
  2. {  
  3. public class LengthyTaskHandler:IHttpHandler  
  4. {  
  5. public void ProcessRequest(HttpContext context)  
  6. {  
  7. System.Threading.Thread.Sleep(10000);  
  8. context.Response.ContentType = "text/plain";  
  9. content.Response.Write("Processing successful!");  
  10. }  
  11. public bool IsReusable  
  12. {  
  13. get  
  14. {  
  15. return false;  
  16. }  
  17. }  
  18. }  
  19. }  


如你所見,ProcessRequest模擬了一個長時間運行的任務,並返回了「Processing successful!」的消息。

 

6. 經過Error事件捕捉錯誤信息

當咱們把愈來愈複雜的邏輯加到Web Worker裏時,錯誤處理機制是必不可少的。而Web Worker偏偏提供了error事件,供開發者捕捉錯誤信息。下面的代碼展現瞭如何綁定error事件:

 

[javascript]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. $("#btnStart").click(function(){  
  2. var worker = new Worker("scripts/lengthytask.js");  
  3. worker.addEventListener("error", function(evt){  
  4. alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename);  
  5. }, false);  
  6. worker.postMessage(10000);  
  7. });  


如上可見, Worker對象能夠綁定error事件;並且evt對象中包含錯誤所在的代碼文件(evt.filename)、錯誤所在的代碼行數(evt.lineno)、以及錯誤信息(evt.message)。

 

7. 經過terminate()方法終止Web Worker

有些狀況下,咱們可能須要強制終止執行中的Web Worker。Worker對象提供了terminate()來終止自身執行任務,被終止的Worker對象不能被重啓或重用,咱們只能新建另外一個Worker實例來執行新的任務。

總結

Web Worker能夠在後臺執行腳本,而不會阻塞頁面交互。Worker對象分爲兩種:專用式Web Worker和共享式Web Worker:專用式的Web Worker只能被當個頁面使用,而共享式的Web Worker能夠在被多個頁面使用。另外,本文還介紹了Web Worker的錯誤處理機制,以及使用Ajax與服務端交互。

相關文章
相關標籤/搜索