再談JavaScript線程,談JavaScript線程

來源:互聯網
上載者:User

再談JavaScript線程,談JavaScript線程

代碼判斷一:

<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?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標籤。

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.