首頁  >  文章  >  web前端  >  HTML5 Web Worker的使用實例教學

HTML5 Web Worker的使用實例教學

小云云
小云云原創
2018-01-08 11:20:411623瀏覽

Web Worker是HTML5提供的一個javascript多執行緒解決方案,我們可以將一些大運算量的程式碼交由web Worker運行而不凍結使用者介面。本文主要介紹了淺談HTML5 Web Worker的使用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧,希望能幫助大家。

一:如何使用Worker

Web Worker的基本原理就是在目前javascript的主執行緒中,使用Worker類別來載入一個javascript檔來開啟一個新的執行緒,起到互不阻塞執行的效果,並且提供主線程和新線程之間資料交換的介面:postMessage,onmessage。

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


//worker.js
onmessage =function (evt){
  var d = evt.data;//通过evt.data获得发送来的数据
  postMessage( d );//将获取到的数据发送会主线程
}

HTML頁面:test.html


##

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <script type="text/javascript">
//WEB页主线程
var worker =new Worker("worker.js"); //创建一个Worker对象并向它传递将在新线程中执行的脚本的URL
 worker.postMessage("hello world");     //向worker发送数据
 worker.onmessage =function(evt){     //接收worker传过来的数据函数
   console.log(evt.data);              //输出worker发送来的数据
 }
 </script>
 </head>
 <body></body>
</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的常用實作為: 


var fibonacci =function(n) {
    return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);
};
//fibonacci(36)

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

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


//fibonacci.js
var fibonacci =function(n) {
    return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);
};
onmessage =function(event) {
    var n = parseInt(event.data, 10);
    postMessage(fibonacci(n));
};

HTML頁面:fibonacci.html


<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>web worker fibonacci</title>
<script type="text/javascript">
  onload =function(){
      var worker =new Worker(&#39;fibonacci.js&#39;);  
      worker.addEventListener(&#39;message&#39;, function(event) {
        var timer2 = (new Date()).valueOf();
           console.log( &#39;结果:&#39;+event.data, &#39;时间:&#39;+ timer2, &#39;用时:&#39;+ ( timer2  - timer ) );
      }, false);
      var timer = (new Date()).valueOf();
      console.log(&#39;开始计算:40&#39;,&#39;时间:&#39;+ timer );
      setTimeout(function(){
          console.log(&#39;定时器函数在计算数列时执行了&#39;, &#39;时间:&#39;+ (new Date()).valueOf() );
      },1000);
      worker.postMessage(40);
      console.log(&#39;我在计算数列的时候执行了&#39;, &#39;时间:&#39;+ (new Date()).valueOf() );
  }  
  </script>
</head>
<body>
</body>
</html>

在Chrome中開啟fibonacci.html,控制台得到如下輸出:

開始計算:40 時間:1316508212705

我在計算數列的時候執行了時間:1316508212734
定時器函數在計算數列時執行了時間:1316508213735
結果:102334155 時間:1316508262820 用時:50115

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

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

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

三:Worker的其他嘗試

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

下面這個範例將透過web worker、jsonp、ajax三種不同的方式來載入一個169.42KB大小的JSON資料


// /aj/webWorker/core.js
function $E(id) {
    return document.getElementById(id);
}
onload =function() {
    //通过web worker加载
    $E(&#39;workerLoad&#39;).onclick =function() {
        var url =&#39;http://js.wcdn.cn/aj/mblog/face2&#39;;
        var d = (new Date()).valueOf();
        var worker =new Worker(url);
        worker.onmessage =function(obj) {
            console.log(&#39;web worker: &#39;+ ((new Date()).valueOf() - d));
        };
    };
    //通过jsonp加载
    $E(&#39;jsonpLoad&#39;).onclick =function() {
        var url =&#39;http://js.wcdn.cn/aj/mblog/face1&#39;;
        var d = (new Date()).valueOf();
        STK.core.io.scriptLoader({
            method:&#39;post&#39;,
            url : url,
            onComplete : function() {
                console.log(&#39;jsonp: &#39;+ ((new Date()).valueOf() - d));
            }
        });
    };
    //通过ajax加载
    $E(&#39;ajaxLoad&#39;).onclick =function() {
        var url =&#39;http://js.wcdn.cn/aj/mblog/face&#39;;
        var d = (new Date()).valueOf();
        STK.core.io.ajax({
            url : url,
            onComplete : function(json) {
                console.log(&#39;ajax: &#39;+ ((new Date()).valueOf() - d));
            }
        });
    };
};

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


<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Worker example: load data</title>
<script src="http://js.t.sinajs.cn/STK/js/gaea.1.14.js" type="text/javascript"></script>
<script type="text/javascript" src="http://js.wcdn.cn/aj/webWorker/core.js"></script>
</head>
<body>
    <input type="button" id="workerLoad" value="web worker加载"></input>
    <input type="button" id="jsonpLoad" value="jsonp加载"></input>
    <input type="button" id="ajaxLoad" value="ajax加载"></input>
</body>
</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.不是每個瀏覽器都支援這個新功能

相關推薦:


H5的多執行緒如何實作Web Worker

WebWorkers-前端的高效能運算

PHP socket 伺服器框架workerman

以上是HTML5 Web Worker的使用實例教學的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn