DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> HTML基礎知識 >> HTML5詳解 >> 針對HTML5的Web Worker使用攻略
針對HTML5的Web Worker使用攻略
編輯:HTML5詳解     
這篇文章主要介紹了針對Html5的Web Worker使用攻略,特別是結合worker拿手的JS使用起來十分有效,需要的朋友可以參考下

Web Workers 是 Html5 提供的一個Javascript多線程解決方案,我們可以將一些大計算量的代碼交由web Worker運行而不凍結用戶界面。
一:如何使用Worker

  Web Worker的基本原理就是在當前Javascript的主線程中,使用Worker類加載一個Javascript文件來開辟一個新的線程,起到互不阻塞執行的效果,並且提供主線程和新線程之間數據交換的接口:postMessage,onmessage。

  那麼如何使用呢,我們看一個例子:
 

JavaScript Code復制內容到剪貼板
  1. //worker.JS   
  2. onmessage =function (evt){   
  3.   var d = evt.data;//通過evt.data獲得發送來的數據   
  4.   postMessage( d );//將獲取到的數據發送會主線程   
  5. }  

  HTML頁面:test.Html


 

XML/Html Code復制內容到剪貼板
  1. <!DOCTYPE Html>  
  2. <Html>  
  3. <<span style="width: auto; height: auto; float: none;" id="20_nwp"><a style="text-decoration: none;" mpid="20" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=head&k0=head&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="20_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">head</span></a></span>>  
  4.  <meta http-equiv="Content-Type" content="text/Html; charset=utf-8"/>  
  5.  <script type="text/<span style="width: auto; height: auto; float: none;" id="21_nwp"><a style="text-decoration: none;" mpid="21" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=Javascript&k0=Javascript&kdi0=0&luki=9&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="21_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">Javascript</span></a></span>">  
  6. //WEB頁主線程   
  7. var worker =new Worker("worker.JS"); //創建一個Worker對象並向它傳遞將在新線程中執行的腳本的URL   
  8.  worker.postMessage("hello world");     //向worker發送數據   
  9.  worker.onmessage =function(evt){     //接收worker傳過來的數據<span style="width: auto; height: auto; float: none;" id="22_nwp"><a style="text-decoration: none;" mpid="22" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=%BA%AF%CA%FD&k0=%BA%AF%CA%FD&kdi0=0&luki=2&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="22_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">函數</span></a></span>  
  10.    console.log(evt.<span style="width: auto; height: auto; float: none;" id="23_nwp"><a style="text-decoration: none;" mpid="23" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=data&k0=data&kdi0=0&luki=4&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="23_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">data</span></a></span>);              //輸出worker發送來的數據   
  11.  }   
  12.  </script>  
  13.  </head>  
  14.  <body></body>  
  15. </Html>  

  用Chrome浏覽器打開test.Html後,控制台輸出 ”hello world” 表示程序執行成功。

  通過這個例子我們可以看出使用web worker主要分為以下幾部分

  WEB主線程:

  1.通過 worker = new Worker( url ) 加載一個JS文件來創建一個worker,同時返回一個worker實例。

  2.通過worker.postMessage( data ) 方法來向worker發送數據。

  3.綁定worker.onmessage方法來接收worker發送過來的數據。

  4.可以使用 worker.terminate() 來終止一個worker的執行。

  worker新線程:

  1.通過postMessage( data ) 方法來向主線程發送數據。

  2.綁定onmessage方法來接收主線程發送過來的數據。
  二:Worker能做什麼

  知道了如何使用web worker ,那麼它到底有什麼用,可以幫我們解決那些問題呢。我們來看一個fibonacci數列的例子。

  大家知道在數學上,fibonacci數列被以遞歸的方法定義:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*),而Javascript的常用實現為:

JavaScript Code復制內容到剪貼板
  1.     
  2. var fibonacci =function(n) {   
  3.     return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);   
  4. };   
  5. //fibonacci(36)  

  在Chrome中用該方法進行39的fibonacci數列執行時間為19097毫秒 ,而要計算40的時候浏覽器直接提示腳本忙了。

  由於Javascript是單線程執行的,在求數列的過程中浏覽器不能執行其它Javascript腳本,UI渲染線程也會被掛起,從而導致浏覽器進入僵死狀態。使用web worker將數列的計算過程放入一個新線程裡去執行將避免這種情況的出現。具體看例子:
 

JavaScript Code復制內容到剪貼板
  1. //fibonacci.JS   
  2. var fibonacci =function(n) {   
  3.     return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);   
  4. };   
  5. onmessage =function(event) {   
  6.     var n = parseInt(event.<span style="width: auto; height: auto; float: none;" id="16_nwp"><a style="text-decoration: none;" mpid="16" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=data&k0=data&kdi0=0&luki=4&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="16_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">data</span></a></span>, 10);   
  7.     postMessage(fibonacci(n));   
  8. };  

  HTML頁面:fibonacci.Html
 

XML/Html Code復制內容到剪貼板
  1. <!DOCTYPE Html>  
  2. <Html>  
  3. <<span style="width: auto; height: auto; float: none;" id="11_nwp"><a style="text-decoration: none;" mpid="11" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=head&k0=head&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="11_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">head</span></a></span>>  
  4. <meta http-equiv="Content-Type" content="text/Html; charset=utf-8"/>  
  5. <title>web worker fibonacci</title>  
  6. <script type="text/<span style="width: auto; height: auto; float: none;" id="12_nwp"><a style="text-decoration: none;" mpid="12" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=Javascript&k0=Javascript&kdi0=0&luki=9&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="12_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">Javascript</span></a></span>">  
  7.   onload =function(){   
  8.       var worker =new Worker('fibonacci.JS');     
  9.       worker.addEventListener('message', function(event) {   
  10.         var timer2 = (new Date()).valueOf();   
  11.            console.log( '結果:'+event.<span style="width: auto; height: auto; float: none;" id="13_nwp"><a style="text-decoration: none;" mpid="13" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=data&k0=data&kdi0=0&luki=4&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="13_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">data</span></a></span>, '時間:'+ timer2, '用時:'+ ( timer2  - timer ) );   
  12.       }, false);   
  13.       var timer = (new Date()).valueOf();   
  14.       console.log('開始計算:40','時間:'+ timer );   
  15.       setTimeout(function(){   
  16.           console.log('定時器<span style="width: auto; height: auto; float: none;" id="14_nwp"><a style="text-decoration: none;" mpid="14" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=%BA%AF%CA%FD&k0=%BA%AF%CA%FD&kdi0=0&luki=2&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="14_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">函數</span></a></span>在計算數列時執行了', '時間:'+ (new Date()).valueOf() );   
  17.       },1000);   
  18.       worker.postMessage(40);   
  19.       console.log('我在計算數列的時候執行了', '時間:'+ (new Date()).valueOf() );   
  20.   }     
  21.   </script>  
  22. </<span style="width: auto; height: auto; float: none;" id="15_nwp"><a style="text-decoration: none;" mpid="15" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=head&k0=head&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="15_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">head</span></a></span>>  
  23. <body>  
  24. </body>  
  25. </Html>  

  在Chrome中打開fibonacci.Html,控制台得到如下輸出:
 
開始計算:40 時間:1316508212705
我在計算數列的時候執行了 時間:1316508212734
定時器

XML/Html Code復制內容到剪貼板
  1. <span style="width: auto; height: auto; float: none;" id="9_nwp"><a style="text-decoration: none;" mpid="9" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=%BA%AF%CA%FD&k0=%BA%AF%CA%FD&kdi0=0&luki=2&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="9_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">函數</span></a></span>  

在計算數列時執行了 時間:1316508213735
結果:102334155 時間:1316508262820 用時:50115

  這個例子說明在worker中執行的fibonacci數列的計算並不會影響到主線程的代碼執行,完全在自己獨立的線程中計算,只是在計算完成之後將結果發回主線程。

  利用web worker我們可以在前端執行一些復雜的大量運算而不會影響頁面的展示,並且不會彈出惡心的腳本正忙提示。

  下面這個例子使用了web worker來計算場景中的像素,場景打開時是一片一片進行繪制的,一個worker只計算一塊像素值。

  http://nerget.com/rayjs-mt/rayJS.Html
  三:Worker的其他嘗試

  我們已經知道Worker通過接收一個URL來創建一個worker,那麼我們是否可以利用web worker來做一些類似jsonp的請求呢,大家知道jsonp是通過插入script標簽來加載JSon數據的,而script元素在加載和執行過程中都是阻塞式的,如果能利用web worker實現異步加載將會非常不錯。

  下面這個例子將通過 web worker、JSonp、AJax三種不同的方式來加載一個169.42KB大小的JSON數據


 

JavaScript Code復制內容到剪貼板
  1. // /aj/webWorker/core.JS   
  2. function $E(id) {   
  3.     return document.getElementById(id);   
  4. }   
  5. onload =function() {   
  6.     //通過web worker加載   
  7.     $E('workerLoad').onclick =function() {   
  8.         var url ='http://JS.wcdn.cn/aj/mblog/face2';   
  9.         var d = (new Date()).valueOf();   
  10.         var worker =new Worker(url);   
  11.         worker.onmessage =function(obj) {   
  12.             console.log('web worker: '+ ((new Date()).valueOf() - d));   
  13.         };   
  14.     };   
  15.     //通過JSonp加載   
  16.     $E('JSonpLoad').onclick =function() {   
  17.         var url ='http://JS.wcdn.cn/aj/mblog/face1';   
  18.         var d = (new Date()).valueOf();   
  19.         STK.core.io.scriptLoader({   
  20.             method:'post',   
  21.             url : url,   
  22.             onComplete : function() {   
  23.                 console.log('JSonp: '+ ((new Date()).valueOf() - d));   
  24.             }   
  25.         });   
  26.     };   
  27.     //通過<span style="width: auto; height: auto; float: none;" id="8_nwp"><a style="text-decoration: none;" mpid="8" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=AJax&k0=AJax&kdi0=0&luki=8&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="8_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">AJax</span></a></span>加載  
  28.     $E('AJaxLoad').onclick =function() {   
  29.         var url ='http://JS.wcdn.cn/aj/mblog/face';   
  30.         var d = (new Date()).valueOf();   
  31.         STK.core.io.AJax({   
  32.             url : url,   
  33.             onComplete : function(JSon) {   
  34.                 console.log('AJax: '+ ((new Date()).valueOf() - d));   
  35.             }   
  36.         });   
  37.     };   
  38. };  

  HTML頁面:/aj/webWorker/worker.Html


 

XML/Html Code復制內容到剪貼板
  1. <!DOCTYPE Html>  
  2. <Html>  
  3. <<span style="width: auto; height: auto; float: none;" id="4_nwp"><a style="text-decoration: none;" mpid="4" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=head&k0=head&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="4_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">head</span></a></span>>  
  4. <meta http-equiv="Content-Type" content="text/Html; charset=utf-8"/>  
  5. <title>Worker example: load <span style="width: auto; height: auto; float: none;" id="5_nwp"><a style="text-decoration: none;" mpid="5" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=data&k0=data&kdi0=0&luki=4&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="5_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">data</span></a></span></title>  
  6. <script src="http://js.t.sinajs.cn/STK/js/gaea.1.14.JS" type="text/<span style="width: auto; height: auto; float: none;" id="6_nwp"><a style="text-decoration: none;" mpid="6" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=Javascript&k0=Javascript&kdi0=0&luki=9&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="6_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">Javascript</span></a></span>"></script>  
  7. <script type="text/Javascript" src="http://js.wcdn.cn/aj/webWorker/core.JS"></script>  
  8. </head>  
  9. <body>  
  10.     <input type="button" id="workerLoad" value="web worker加載"></input>  
  11.     <input type="button" id="JSonpLoad" value="JSonp加載"></input>  
  12.     <input type="button" id="<span style="width: auto; height: auto; float: none;" id="7_nwp"><a style="text-decoration: none;" mpid="7" target="_blank" href="http://cpro.baidu.com/cpro/ui/uiJS.PHP?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=0&is_app=0&jk=619521ab1ccffd45&k=ajax&k0=AJax&kdi0=0&luki=8&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=45fdcf1cab219561&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F1183%2EHtml&urlid=0" id="7_nwl"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">AJax</span></a></span>Load" value="AJax加載"></input>  
  13. </body>  
  14. </Html>  

  設置HOST
 

復制代碼代碼如下: 127.0.0.1 JS.wcdn.cn 

  通過 http://JS.wcdn.cn/aj/webWorker/worker.Html 訪問頁面然後分別通過三種方式加載數據,得到控制台輸出:
 

復制代碼代碼如下: web worker: 174
JSonp: 25
AJax: 38

  多試幾次發現通過JSonp和AJax加載數據的時間相差不大,而web worker的加載時間一直處於高位,所以用web worker來加載數據還是比較慢的,即便是大數據量情況下也沒任何優勢,可能是Worker初始化新起線程比較耗時間。除了在加載過程中是無阻塞的之外沒有任何優勢。

  那麼web worker是否能支持跨域JS加載呢,這次我們通過http://127.0.0.1/aj/webWorker/worker.Html 來訪問頁面,當點擊 ”web worker加載” 加載按鈕時Chrome下無任何反映,FF6下提示錯誤。由此我們可以知道web worker是不支持跨域加載JS的,這對於將靜態文件部署到單獨的靜態服務器的網站來說是個壞消息。

所以web worker只能用來加載同域下的JSon數據,而這方面AJax已經可以做到了,而且效率更高更通用。還是讓Worker做它自己擅長的事吧。
  四:總結

  web worker看起來很美好,但處處是魔鬼。

  我們可以做什麼:

  1.可以加載一個JS進行大量的復雜計算而不掛起主進程,並通過postMessage,onmessage進行通信

  2.可以在worker中通過importScripts(url)加載另外的腳本文件

  3.可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()

  4.可以使用XMLHttpRequest來發送請求

  5.可以訪問navigator的部分屬性

  有那些局限性:

  1.不能跨域加載JS

  2.worker內代碼不能訪問DOM

  3.各個浏覽器對Worker的實現不大一致,例如FF裡允許worker中創建新的worker,而Chrome中就不行

  4.不是每個浏覽器都支持這個新特性

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved