成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

聊聊webWorker

luffyZh / 2237人閱讀

摘要:不過,這并不意味著語言本身就支持了多線程,對于語言本身它仍是運(yùn)行在單線程上的,只是瀏覽器宿主環(huán)境提供的一個能力。主線程與子線程之間也可以交換二進(jìn)制數(shù)據(jù),比如等對象,也可以在線程之間發(fā)送。

先看幾個例子

本例子是通過通過紅點(diǎn)展示地球上的地震帶,數(shù)據(jù)來自于地質(zhì)探測局
通過console.log看到數(shù)據(jù)運(yùn)算所耗的時間
不使用 webworker No web workers - all on main thread
使用一條 webworker One web worker
使用兩條 Two web workers
使用八條 Eight web workers
使用20條 20 web workers

結(jié)論:是? // 帶著思考看下去

背景

JavaScript引擎是單線程運(yùn)行的,JavaScript中耗時的I/O操作都被處理為異步操作,它們包括鍵盤、鼠標(biāo)I/O輸入輸出事件、窗口大小的resize事件、定時器(setTimeout、setInterval)事件、Ajax請求網(wǎng)絡(luò)I/O回調(diào)等。當(dāng)這些異步任務(wù)發(fā)生的時候,它們將會被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到JavaScript運(yùn)行時執(zhí)行線程空閑時候才會按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。

雖然JS運(yùn)行在瀏覽器中,是單線程的,每個window一個JS線程,但瀏覽器不是單線程的,例如Webkit或是Gecko引擎,都可能有如下線程:

javascript引擎線程
界面渲染線程
瀏覽器事件觸發(fā)線程
Http請求線程

很多人覺得異步(promise async/await),都是通過類似event loop在平常的工作中已經(jīng)足夠,但是如果做復(fù)雜運(yùn)算,這些異步偽線程的不足就逐漸體現(xiàn)出來,比如settimeout拿到的值并不正確,再者假如頁面有復(fù)雜運(yùn)算的時候頁面很容易觸發(fā)假死狀態(tài),
為了有多線程功能,webworker問世了。不過,這并不意味著 JavaScript 語言本身就支持了多線程,對于 JavaScript 語言本身它仍是運(yùn)行在單線程上的, Web Worker 只是瀏覽器(宿主環(huán)境)提供的一個能力/API

簡介

Web Worker 是HTML5標(biāo)準(zhǔn)的一部分,這一規(guī)范定義了一套 API,它允許一段JavaScript程序運(yùn)行在主線程之外的另外一個線程中。工作線程允許開發(fā)人員編寫能夠長時間運(yùn)行而不被用戶所中斷的后臺程序, 去執(zhí)行事務(wù)或者邏輯,并同時保證頁面對用戶的及時響應(yīng),可以將一些大量計算的代碼交給web worker運(yùn)行而不凍結(jié)用戶界面,后面會有案例介紹

類型

Web workers可分為兩種類型:專用線程dedicated web worker,以及共享線程shared web workerDedicated web worker隨當(dāng)前頁面的關(guān)閉而結(jié)束;這意味著Dedicated web worker只能被創(chuàng)建它的頁面訪問。與之相對應(yīng)的Shared web worker可以被多個頁面訪問。在Javascript代碼中,“Work”類型代表Dedicated web worker,而“SharedWorker”類型代表Shared web worker。
Shared Worker則可以被多個頁面所共享(同域情況下)

如何創(chuàng)建

Web Worker的創(chuàng)建是在主線程當(dāng)中通過傳入文件的url來實(shí)現(xiàn)的。如下所示:

let webworker = new Worker("myworker.js");

返回的是webworker實(shí)例對象,該對象是主線程和其他線程的通訊橋梁
主線程和其他線程可以通過

onmessage: 監(jiān)聽事件
postmessage: 傳送事件

相關(guān)的API進(jìn)行通訊
案例代碼如下

//主線程 main.js
var worker = new Worker("worker.js");
worker.onmessage = function(event){
    // 主線程收到子線程的消息
};
// 主線程向子線程發(fā)送消息
worker.postMessage({
    type: "start",
    value: 12345
});

//web worker.js
onmessage = function(event){
   // 收到
};
postMessage({
    type: "debug",
    message: "Starting processing..."
});

相關(guān)demo

如何終止

如果在某個時機(jī)不想要 Worker 繼續(xù)運(yùn)行了,那么我們需要終止掉這個線程,可以調(diào)用 在主線程workerterminate 方法 或者在相應(yīng)的線程中調(diào)用close

// 方式一 main.js 在主線程停止方式 
var worker = new Worker("./worker.js");
...
worker.terminate();

// 方式二、worker.js
self.close()
錯誤機(jī)制

提供了onerror API

worker.addEventListener("error", function (e) {
  console.log("MAIN: ", "ERROR", e);
  console.log("filename:" + e.filename + "-message:" + e.message + "-lineno:" + e.lineno);
});

// event.filename: 導(dǎo)致錯誤的 Worker 腳本的名稱;
// event.message: 錯誤的信息;
// event.lineno: 出現(xiàn)錯誤的行號;
sharedWorker

對于 Web Worker ,一個 tab 頁面只能對應(yīng)一個 Worker 線程,是相互獨(dú)立的;
SharedWorker 提供了能力能夠讓不同標(biāo)簽中頁面共享的同一個 Worker 腳本線程;
當(dāng)然,有個很重要的限制就是它們需要滿足同源策略,也就是需要在同域下;
在頁面(可以多個)中實(shí)例化 Worker 線程:

// main.js

var myWorker = new SharedWorker("worker.js");

myWorker.port.start();

myWorker.port.postMessage("hello, I"m main");

myWorker.port.onmessage = function(e) {
  console.log("Message received from worker");
}
// worker.js
onconnect = function(e) {
  var port = e.ports[0];

  port.addEventListener("message", function(e) {
    var workerResult = "Result: " + (e.data[0]);
    port.postMessage(workerResult);
  });
  port.start();
}

在線demo

父子線程

線程中再創(chuàng)建線程

環(huán)境與作用域

Worker 線程的運(yùn)行環(huán)境中沒有 window 全局對象,也無法訪問 DOM 對象,所以一般來說他只能來執(zhí)行純 JavaScript 的計算操作。但是,他還是可以獲取到部分瀏覽器提供的 API 的:

setTimeout(), clearTimeout(), setInterval(), clearInterval():有了設(shè)計個函數(shù),就可以在 Worker : 線程中可以再創(chuàng)建worker;
XMLHttpRequest : 對象:意味著我們可以在 Worker 線程中執(zhí)行 ajax 請求;
navigator 對象:可以獲取到 ppName,appVersion,platform,userAgent 等信息;
location 對象(只讀):可以獲取到有關(guān)當(dāng)前 URL 的信息;
Application Cache
indexedDB
WebSocket、
Promise、

庫或外部腳本引入和訪問

在線程中,提供了importScripts方法
如果線程中使用了importScripts 一般按照以下步驟解析

1、解析 importScripts方法的每一個參數(shù)。
2、如果有任何失敗或者錯誤,拋出 SYNTAX_ERR 異常。
3、嘗試從用戶提供的 URL 資源位置處獲取腳本資源。
4、對于 importScripts 方法的每一個參數(shù),按照用戶的提供順序,獲取腳本資源后繼續(xù)進(jìn)行其它操作。
// worker.js
importScripts("math_utilities.js"); 
onmessage = function (event) 
 { 
     var first=event.data.first; 
     var second=event.data.second; 
     calculate(first,second); // calculate 是math_utilities.js中的方法 
 }; 

也可以一次性引入多個

//可以多起一次傳入
importScripts("script1.js", "script2.js");
XMLHttpRequest
onmessage = function(evt){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "serviceUrl"); //serviceUrl為后端j返回son數(shù)據(jù)的接口
    xhr.onload = function(){
    postMessage(xhr.responseText);
    };
    xhr.send();
}
jsonp
// 設(shè)置jsonp
function MakeServerRequest() 
{
    importScripts("http://SomeServer.com?jsonp=HandleRequest");
} 

// jsonp回調(diào)
function HandleRequest(objJSON) 
{
    postMessage("Data returned from the server...FirstName: " 
                  + objJSON.FirstName + " LastName: " + objJSON.LastName);
} 

// Trigger the server request for the JSONP data 
MakeServerRequest();
通訊原理

從一個線程到另一個線程的通訊實(shí)際上是一個值拷貝的過程,實(shí)際上是先將數(shù)據(jù)JSON.stringify之后再JSON.parse。主線程與子線程之間也可以交換二進(jìn)制數(shù)據(jù),比如File、Blob、ArrayBuffer等對象,也可以在線程之間發(fā)送。但是,用拷貝方式發(fā)送二進(jìn)制數(shù)據(jù),會造成性能問題。比如,主線程向子線程發(fā)送一個50MB文件,默認(rèn)情況下瀏覽器會生成一個原文件的拷貝。為了解決這個問題,JavaScript允許主線程把二進(jìn)制數(shù)據(jù)直接轉(zhuǎn)移給子線程,轉(zhuǎn)移后主線程無法再使用這些數(shù)據(jù),這是為了防止出現(xiàn)多個線程同時修改數(shù)據(jù)的問題,這種轉(zhuǎn)移數(shù)據(jù)的方法,叫做Transferable Objects。
不過現(xiàn)在很多瀏覽器支持transferable objects(可轉(zhuǎn)讓對象) ,這個技術(shù)是零拷貝轉(zhuǎn)移,能大大提升性能,
可以指定傳送的數(shù)據(jù)全都是零拷貝

var abBuffer = new ArrayBuffer(32);
aDedicatedWorker.postMessage(abBuffer, [abBuffer]);

也可以 指定某個是 使用 零拷貝

var objData = {
   "employeeId": 103,
   "name": "Sam Smith",
   "dateHired": new Date(2006, 11, 15),
   "abBuffer": new ArrayBuffer(32)
};
aDedicatedWorker.postMessage(objData, [objData.abBuffer]);
工作線程生命周期

工作線程之間的通信必須依賴于瀏覽器的上下文環(huán)境,并且通過它們的 MessagePort 對象實(shí)例傳遞消息。每個工作線程的全局作用域都擁有這些線程的端口列表,這些列表包括了所有線程使用到的 MessagePort 對象。在專用線程的情況下,這個列表還會包含隱式的 MessagePort 對象。
每個工作線程的全局作用域?qū)ο?WorkerGlobalScope 還會有一個工作線程的線程列表,在初始化時這個列表為空。當(dāng)工作線程被創(chuàng)建的時候或者擁有父工作線程的時候,它們就會被填充進(jìn)來。
最后,每個工作線程的全局作用域?qū)ο?b> WorkerGlobalScope 還擁有這個線程的文檔模型,在初始化時這個列表為空。當(dāng)工作線程被創(chuàng)建的時候,文檔對象就會被填充進(jìn)來。無論何時當(dāng)一個文檔對象被丟棄的時候,它就要從這個文檔對象列舉里面刪除出來。

性能測試
初始化測試
// 部分機(jī)器webwoker初始化時間
Macbook Pro: 2 workers, 0.4 milliseconds on average
Macbook Pro: 4 workers, 0.6 milliseconds on average
Nexus 5: 2 workers, 6 milliseconds on average
Nexus 5: 4 workers, 15 milliseconds on average (border-line UI jank)
傳輸速度測試

1、普通json/object

2、tranferable objects


可見 transferable objects傳輸速度要高很多

部分典型的應(yīng)用場景如下

1) 使用專用線程進(jìn)行數(shù)學(xué)運(yùn)算
Web Worker最簡單的應(yīng)用就是用來做后臺計算,而這種計算并不會中斷前臺用戶的操作
2) 圖像處理
通過使用從或者元素中獲取的數(shù)據(jù),可以把圖像分割成幾個不同的區(qū)域并且把它們推送給并行的不同Workers來做計算
3) 大量數(shù)據(jù)的檢索
當(dāng)需要在調(diào)用 ajax后處理大量的數(shù)據(jù),如果處理這些數(shù)據(jù)所需的時間長短非常重要,可以在Web Worker中來做這些,避免凍結(jié)UI線程
4) 背景數(shù)據(jù)分析
由于在使用Web Worker的時候,我們有更多潛在的CPU可用時間,我們現(xiàn)在可以考慮一下JavaScript中的新應(yīng)用場景。例如,我們可以想像在不影響UI體驗(yàn)的情況下實(shí)時處理用戶輸入。利用這樣一種可能,我們可以想像一個像Word(Office Web Apps 套裝)一樣的應(yīng)用:當(dāng)用戶打字時后臺在詞典中進(jìn)行查找,幫助用戶自動糾錯等等。

限制

1、不能訪問DOM和BOM對象的,Location和navigator的只讀訪問,并且navigator封裝成了WorkerNavigator對象,更改部分屬性。無法讀取本地文件系統(tǒng)
2、子線程和父級線程的通訊是通過值拷貝,子線程對通信內(nèi)容的修改,不會影響到主線程。在通訊過程中值過大也會影響到性能(解決這個問題可以用transferable objects
3、并非真的多線程,多線程是因?yàn)闉g覽器的功能
4、兼容性
5 因?yàn)榫€程是通過importScripts引入外部的js,并且直接執(zhí)行,其實(shí)是不安全的,很容易被外部注入一些惡意代碼
6、條數(shù)限制,大多瀏覽器能創(chuàng)建webworker線程的條數(shù)是有限制的,雖然可以手動去拓展,但是如果不設(shè)置的話,基本上都在20條以內(nèi),每條線程大概5M左右,需要手動關(guān)掉一些不用的線程才能夠創(chuàng)建新的線程(相關(guān)解決方案)
7、js存在真的線程的東西,比如SharedArrayBuffer

js的多線程庫

1、tagg2

參考文獻(xiàn):[1] https://www.html5rocks.com/zh...
[2] http://www.alloyteam.com/2015...
[3] https://typedarray.org/concur...
[4] http://www.andygup.net/advanc...
[5] https://developer.mozilla.org...
[6] http://coolaj86.github.io/htm...
[7] http://www.xyhtml5.com/webwor...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/91691.html

相關(guān)文章

  • WebWork(在主線程創(chuàng)建子進(jìn)程)

    摘要:淺談前言都知道是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死,以及在進(jìn)行大量的循環(huán)計算時會導(dǎo)致線程阻塞由于要進(jìn)行大量的計算后面的運(yùn)行會被阻隔在此處,使得性能較差,代碼維護(hù)性差等一系列的問題發(fā)生。 WebWork淺談 前言: 都知道JS是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死, 以及在進(jìn)行大量的for循環(huán)計算時會導(dǎo)致線程阻塞,由于要進(jìn)行...

    eccozhou 評論0 收藏0
  • WebWork(在主線程創(chuàng)建子進(jìn)程)

    摘要:淺談前言都知道是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死,以及在進(jìn)行大量的循環(huán)計算時會導(dǎo)致線程阻塞由于要進(jìn)行大量的計算后面的運(yùn)行會被阻隔在此處,使得性能較差,代碼維護(hù)性差等一系列的問題發(fā)生。 WebWork淺談 前言: 都知道JS是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死, 以及在進(jìn)行大量的for循環(huán)計算時會導(dǎo)致線程阻塞,由于要進(jìn)行...

    wmui 評論0 收藏0
  • WebWork(在主線程創(chuàng)建子進(jìn)程)

    摘要:淺談前言都知道是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死,以及在進(jìn)行大量的循環(huán)計算時會導(dǎo)致線程阻塞由于要進(jìn)行大量的計算后面的運(yùn)行會被阻隔在此處,使得性能較差,代碼維護(hù)性差等一系列的問題發(fā)生。 WebWork淺談 前言: 都知道JS是單線程語言,最讓人頭疼的莫過于在網(wǎng)絡(luò)正常的情況下經(jīng)常出現(xiàn)頁面的假死, 以及在進(jìn)行大量的for循環(huán)計算時會導(dǎo)致線程阻塞,由于要進(jìn)行...

    scq000 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<