首頁 > web前端 > js教程 > 再談JavaScript執行緒_javascript技巧

再談JavaScript執行緒_javascript技巧

WBOY
發布: 2016-05-16 15:50:40
原創
2286 人瀏覽過

程式碼判斷一:

<div id="div">
  click me
</div>

<script>
  var div=document.getElementById("div");
  div.addEventListener('click',function(){
   alert('You have clicked me!');
  });
  for(var i =0; i<999999999;i++){
   console.log(i);
  }
</script>

登入後複製

執行之,不出意外的話所有瀏覽器都會卡死,因為上面的for循環次數太多了,非常耗費CPU資源,而基於JavaScript單線程的事實,瀏覽器UI渲染被掛起而導致假死。

       現在問題來了,我就是想要實現上述程式碼,怎麼辦?

Concurrent.Thread.js
       此類別庫實質上或使用setTimeout來實作一個「假的多執行緒」。在HTML5 WebWorker問世之前是一個很好的選擇。例如我們要實作上述“程式碼片段一”,可以這樣寫(點我下載類別庫):

程式碼片段二:

<div id="div">
  click me
</div>
<script src="Concurrent.Thread.js"></script>
<script>
  Concurrent.Thread.create(function(){
    var div=document.getElementById("div");
    div.addEventListener('click',function(){
     alert('You have clicked me!');
    });
    for(var i =0; i<9999999;i++){
     console.log(i);
    }
  });
</script>

登入後複製

 透過該類別庫提供的create方法可以建立一個「新執行緒」。另外,將script標籤的type屬性設定為 text/x-script.multithreaded-js 也可以達到相同的效果:

程式碼片段三:

<div id="div">
  click me
</div>
<script src="Concurrent.Thread.js"></script>
<script type="text/x-script.multithreaded-js">
    var div=document.getElementById("div");
    div.addEventListener('click',function(){
     alert('You have clicked me!');
    });
    for(var i =0; i<9999999;i++){
     console.log(i);
    }
</script>
登入後複製

WebWorker
    針對以上瀏覽器卡死這種糟糕的使用者體驗,HTML5怎麼會熟視無睹呢?

     下面我們用經典的斐波那契數列來做測試:

程式碼片段四:

主頁:

<div id="div"></div>
<script>
  window.onload=function(){
     var div=document.getElementById("div");
     if(typeof(Worker)!=="undefined"){//在创建WebWorker之前,先判断浏览器是否支持
        console.log("Start calculating....");
       var time1= new Date()*1;//获得当前时间戳
       var worker=new Worker("fibonacci.js");//创建WebWorker对象,并传递在新线程中将要执行的脚本的路径
       worker.onmessage=function(e){ //监听从新线程发送过来的数据
         div.innerHTML=e.data;
         var time2=new Date()*1;
         console.log("time spend:"+(time2-time1)+"ms");
       }
        
       worker.postMessage(36);//向新线程发送数据
     }else{
       alert("Your browser do not support WebWoker");
     }
  }
</script>

fibonacci.js:
var fibonacci=function (n){
  return n<3&#63;n:(arguments.callee(n-1)+arguments.callee(n-2));
}
onmessage=function(e){
  var num=parseInt(e.data,10);
  postMessage(fibonacci(num));//向主页面发送数据
}

登入後複製

基本的使用方法已在程式碼中做註解了,檢視控制台,可以看見很快就列印出執行時間了。所以我們得出的結論是:WebWorker適合在前端執行複雜的大量的計算。要注意的是,WebWorker不支援跨域,本地測試還是用http協議,不要用file協議,否則不能創建Worker對象而報腳本錯誤 。

        如果我們需要連續執行多個postMessage操作,最好不要work.postMessage一直寫,像這樣:

    worker.postMessage(36);

    worker.postMessage(36);

    worker.postMessage(36);

登入後複製

       因為此時只有一個WebWorker實例,postMessage會依序執行而非非同步執行,就無法充分發揮它的效能了。可以透過建立多個WebWorker實例來傳送資料。

        需要注意的幾點事項有:

        1、我們觀察到WebWorker透過接受一個url來創建一個worker,而jsonp的實現原理就是透過動態插入script標籤載入數據,那我們嘗試用WebWorker來實現同樣的事情不是更好嗎?因為WebWorker是多執行緒的,沒有阻塞,豈不美哉?但實際上經過實驗,我們發現WebWorker表現不如意。所以這並不是它擅長的事,我們還是不要讓它越俎代庖的好。

        2、WebWorker在接受其他來源資訊的時候,其實也為網站的安全帶來了隱患,如果接收不明來源的腳本訊息,可能會導致XSS注入攻擊。所以這一點需要防範,其實我們上面範例中使用innerHTML是不安全的,可以使用innerText或現代瀏覽器提供的textContent來替代,以過濾掉html標籤。

  今天比較累了,想睡覺了,先寫這麼多吧。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板