首頁  >  文章  >  web前端  >  HTML5多執行緒JavaScript解決方案Web Worker-專用Worker和共享Worker的詳細程式碼介紹

HTML5多執行緒JavaScript解決方案Web Worker-專用Worker和共享Worker的詳細程式碼介紹

黄舟
黄舟原創
2017-03-11 16:18:182123瀏覽

不得不說,HTML5確實提供了大量強大的功能特性
甚至顛覆了我們之前理解的JavaScript單線程
它提供了JavaScript多線程的解決方案
這個新特性叫做Web Worker
(在此之前沒有多線程,setTimeout等本質仍然是單線程)
雖然是多線程編程
不過我們不用擔心傳統的多線程語言C++、Java等等遇到的多線程問題
下面我們就來看看什麼是Web Worker

專用Worker

專用Worker(Dedicated Worker)是最常用的Web Worker
而且各個瀏覽器實現的還不錯

聲明

什麼時候我們需要多執行緒呢
比如說我們需要複雜的計算、

//demo.jsfunction calculate(){
  var ret = 0;  for(var i = 1; i <= 1e9; i++){
    ret += i;
  }  return ret;
}var result;var start;var end;
start = +new Date();
result = calculate();
end = +new Date();
console.log(result); //500000000067109000console.log(end - start); //977

我們計算了從1加到10億的值
讓頁面的渲染停了將近1秒鐘
對於用戶的體驗來說是相當不友好的
雖然開發中不會有這麼喪心病狂的計算
但是可能會遇到密集而又複雜的任務
這時我們也許會希望開闢一個獨立的新線程來完成
而我們只需要關注結果值


HTML5允許我們使用Worker執行緒
它的工作內容需要寫在一個獨立的js檔案中
讓我們的多個程式區塊並發運行

var worker = new Worker(&#39;scripts/worker.js&#39;);

透過這種方式來實例化一個worker
參數是js檔案的路徑(HTML主檔案和Worker檔案需要滿足同源策略)
當程式運行到這裡時
這個檔案就會被載入到一個Worker中
瀏覽器就會啟動一個獨立執行緒運行該js檔案

互動

我們的主執行緒和工作執行緒是基於事件的機制來進行互動的
換句話說,
它們都需要訂閱事件來互相通訊(onmessage事件)

//主线程
worker.addEventListener(&#39;message&#39;, function(e){
    //e.data为从worker线程得到的数据
});
worker.possMessage(...);//向worker线程发送数据
//工作线程
addEventListener(&#39;message&#39;, function(e){
    //e.data为从主线程得到的数据
});
possMessage(...);//向主线程发送数据

它們的資料綁定和資料發送時類似的
只不過在worker檔案中不需要用物件呼叫API
這樣我們剛才的複雜計算就可以讓worker來做

//worker.jsfunction calculate(){
  var ret = 0;  for(var i = 1; i <= 1e9; i++){
    ret += i;
  }  return ret;
}
postMessage(calculate());
//demo.jsvar worker = new Worker(&#39;scripts/worker.js&#39;);
worker.addEventListener('message', function(e){
  console.log(e.data); //500000000067109000}, false);

在HTML5的Web Worker規範中
worker中還可以實例化它自己的worker(感覺沒什麼必要啊)
稱為subworker(線程嵌套線程)
不過我測試了一下,chrome暫時還不支援subworker
但是據說Firefox支援

#終止

既然我們可以創建worker
那麼我們也應該可以終止worker讓它停止工作
在主執行緒和工作執行緒中都可以終止
只需要在worker物件或worker的作用域中呼叫API
一個是我們讓它結束工作
一個是它自己罷工

//主线程worker.terminate();
//工作线程close();

不過我想我們一般情況下
都會以worker物件上呼叫terminate方法的來終止它
這樣會比較安全

環境

#一開始的時候我就說了
我們不必擔心傳統的多線程語言遇到的多線程問題
比如說為了防止它們搶佔資源而引入的…
無比複雜的鎖機制
為什麼呢?
因為在worker內部
我們根本就無法存取主程式的任何資源
它就是一個完全獨立的執行緒
Web Worker有以下限制:

  • 同源策略限制

  • 不能存取頁面DOM和其他資源

  • #瀏覽器實作程度不同

#不過我們可以在worker內部做這些事情:

  • 可以執行網路操作(Ajax、Web Sockets)

  • 可以使用定時器(set/clearTimeout()、set/clearInterval())

  • 存取某些重要全域變數及功能的複本(navigator、location、JSON、applicationCache)

  • 可以使用importScrips()載入額外js腳本

importScripts(&#39;foo.js&#39;,&#39;bar.js&#39;);importScripts(&#39;foobar.js&#39;);

好奇的話,可以在worker內console.log(this);
查看它的作用域內有什麼

應用

#關於它的應用程式
我們會利用Web Worker做這些事情

  • 複雜數學計算

  • 複雜資料排序

  • #資料處理(壓縮、影像處理…)

  • ##高流量網路通訊

共享Worker

除了專用線程外還有一個共享線程Shared Worker
可以了解一下

剛剛我查了一下

到目前為止,只有Google、火狐還有歐朋實現了這個技術




#如果我們的網站或App可以同時載入多個tab (標籤頁)
那麼如果使用普通的worker我們可能會重複創造多個線程
這必然會佔用系統資源
這時如果我們可以讓App或整站的頁面實例都能夠共享一個worker

那就很棒了~ ###共享執行緒和專用執行緒使用方式差不多,稍微複雜一點點而已###
var worker = new SharedWorker(&#39;scripts/worker.js&#39;);

由于共享线程需要与多个程序实例或页面链接
所以它需要通过某种方式来了解消息的来源
这个方式就是利用一个唯一标识符port(端口)
这样我们刚才的例子就需要写成这个样子

//demo.jsvar worker = new SharedWorker(&#39;scripts/worker.js&#39;);
worker.port.addEventListener('message', function(e){
  console.log(e.data); //500000000067109000}, false);
worker.port.start();

在主线程中
端口连接必须初始化
使用API worker.port.start();

//worker.jsfunction calculate(){
  var ret = 0;  for(var i = 1; i <= 1e9; i++){
    ret += i;
  }  return ret;
}
addEventListener(&#39;connect&#39;, function(e){
  var port = e.ports[0];
  port.start();
  port.postMessage(calculate());
});

在共享worker内部同样需要初始化端口连接port.start();
除此之外,我们还需要处理额外事件onconnect
这个事件为我们的特定连接提供了端口对象
var port = e.ports[0];用于获取连接分配的端口


我们的onmessage事件就可以写在onconnect事件处理函数内部

addEventListener(&#39;connect&#39;, function(e){
  var port = e.ports[0];
  port.addEventListener(&#39;message&#39;, function(e){    ...
    port.postMessage(...);    ...
  });
  port.start();
});

除此之外,其他的功能共享Worker和专用Worker都是一样的

以上是HTML5多執行緒JavaScript解決方案Web Worker-專用Worker和共享Worker的詳細程式碼介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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