web worker

web Worker

web Worker 文件單獨(dú)寫在一個(gè)文件中,在main worker 中 執(zhí)行的文件里使用下面語句啟用 web Worker。 如果引用的文件是存在的,則會異步下載,下載完成后,web worker才會開始。如果資源文件加載失?。?04),worker 回靜默失?。╢ail sliently)。

    var worker = new Worker('task.js');

創(chuàng)建worker 成功后,使用 worker.postMessage() 來啟用它。

使用 Message Passing 與 worker 通信

worker 與上層頁面(Parent Page)通信基于事件系統(tǒng)和 postMessage方法。該方法接收字符或者JSON對象作為唯一的參數(shù),最近新一代的現(xiàn)代瀏覽器支持傳入JSON對象。需要注意的是JSON對象是被復(fù)制傳遞的,worker 和 parent Page 操作的不是一個(gè)實(shí)例,可以理解為在接收數(shù)據(jù)時(shí)經(jīng)歷了編碼和解碼。這個(gè)特性同樣適用于支持文件,二進(jìn)制,ArrayBuffer等類型的瀏覽器。因此當(dāng)使用postMessage傳遞較大文件的時(shí)候需要注意這個(gè)問題。為了解決這個(gè)問題可以使用transferObject[Transferring is effectively recreating the object while sharing a reference to the underlying data and then detaching the object being transferred.]它用于傳遞重型資源的使用權(quán),并不是所有的對象都是適用于使用它。理解為他是引用傳遞,沒有復(fù)制的過程,不同與引用傳遞的是一旦傳遞了該數(shù)據(jù),那么原有的數(shù)據(jù)會被清空不可以再繼續(xù)被使用,他的內(nèi)容被傳遞到worker的上下文環(huán)境中。

main script:

var worker = new Worker('doWork.js');

worker.addEventListener('message', function(e) {
  console.log('Worker said: ', e.data);
}, false);

worker.postMessage('Hello World'); // Send data to our worker.

worker :

self.addEventListener('message', function(e) {
  self.postMessage(e.data);
}, false);

woker 可用功能

可以的:

  • navigator 對象
  • location (只讀)
  • XMLHTTPRequest
  • setTimeout()/clearTimeout() and setInterval()/clearInterval()
  • Application Cache
  • 使用importScripts() 方法加載外部腳本
  • Spawning other web workers

不可以的:

  • 操作DOM
  • window對象
  • document 對象
  • parent 對象

使用 importScripts

importScripts('script1.js');
importScripts('script2.js');

// or

importScripts('script1.js', 'script2.js');

subWorker

webWorker可以spawn subWorker。這有利于在運(yùn)行時(shí)進(jìn)一步分解大任務(wù)。

警告caveart:

  • subWorker 必須與 parent Page 同源
  • subWorker 的 URIs 是被解析為相對于 Parent Workers 資源的。
  • 由于 worker 之間的通信使用的 copied 方式,使用subWorker時(shí)需要注意系統(tǒng)資源的開銷。

inline worker

再執(zhí)行過程中創(chuàng)建一個(gè)worker, 或者創(chuàng)建內(nèi)建頁面而不是獨(dú)立的woker文件。使用 Blob 可以在 main logic 通過創(chuàng)建一個(gè) URL 處理 woker code 。

var blob = new Blob([
    "onmessage = function(e) { postMessage('msg from worker'); }"]);

// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);

var worker = new Worker(blobURL);
worker.onmessage = function(e) {
  // e.data == 'msg from worker'
};
worker.postMessage(); // Start the worker.

這個(gè)巧妙的使用了 window.URL.createObjectURL(),這方法創(chuàng)建了一個(gè)可以引用Dom
File or Blob 對象的簡單的url 字符串。Blob URL 是唯一的并且持續(xù)應(yīng)用的這個(gè)生命周期直到document unload。使用 window.URL.revokeObjectURL 來回收創(chuàng)建的Blob URL()。

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8" />
</head>
<body>

 <div id="log"></div>

 <script id="worker1" type="javascript/worker">
   // This script won't be parsed by JS engines
   // because its type is javascript/worker.
   self.onmessage = function(e) {
     self.postMessage('msg from worker');
   };
   // Rest of your worker code goes here.
 </script>

 <script>
   function log(msg) {
     // Use a fragment: browser will only render/reflow once.
     var fragment = document.createDocumentFragment();
     fragment.appendChild(document.createTextNode(msg));
     fragment.appendChild(document.createElement('br'));

     document.querySelector("#log").appendChild(fragment);
   }

   var blob = new Blob([document.querySelector('#worker1').textContent]);

   var worker = new Worker(window.URL.createObjectURL(blob));
   worker.onmessage = function(e) {
     log("Received: " + e.data);
   }
   worker.postMessage(); // Start the worker.
 </script>
</body>
</html>

這種方式引用外部腳本時(shí),需要使用絕對路徑方式來引用,或者在postMessage里傳入url,手動解析域名拼合出訪問的路徑。

錯(cuò)誤監(jiān)聽和處理

錯(cuò)誤對象的結(jié)構(gòu):

{
filename:// 文件
lineno:// 錯(cuò)誤行數(shù)
message:// 錯(cuò)誤信息
}
 function onError(e) {
    document.getElementById('error').textContent = [
      'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
    ].join('');
  }

  function onMsg(e) {
    document.getElementById('result').textContent = e.data;
  }

  var worker = new Worker('workerWithError.js');
  worker.addEventListener('message', onMsg, false);
  worker.addEventListener('error', onError, false);
  worker.postMessage(); // Start worker without a message.

試用場景

  • 預(yù)加載緩存數(shù)據(jù)
  • 代碼高亮或者實(shí)時(shí)文本格式化
  • 拼寫檢查
  • 解析視頻或音頻數(shù)據(jù)
  • background I/O 或者 webservices 輪詢
  • 處理大量數(shù)組或者JSON響應(yīng)
  • canvas中的圖片過濾
  • 更新本地?cái)?shù)據(jù)庫多條記錄

web Worker

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容