1.JS單線程
說起Web Workers,首先必須了解因為JS運行在瀏覽器中,是單線程的,每個window一個JS線程,既然是單線程的,在某個特定的時刻只有特定的代碼能夠被執行,并阻塞其它的代碼。而瀏覽器是事件驅動的(Event driven),瀏覽器中很多行為是異步(Asynchronized)的,會創建事件并放入執行隊列中。javascript引擎是單線程處理它的任務隊列,你可以理解成就是普通函數和回調函數構成的隊列。當異步事件發生時,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠標點擊事件發生、定時器觸發事件發生、XMLHttpRequest完成回調觸發等),將他們放入執行隊列,等待當前代碼執行完成。
2.Web Workers(多線程)
什么是Web Worker?
web worker 是運行在后臺的 JavaScript,獨立于其他腳本,不會影響頁面的性能。您可以繼續做任何愿意做的事情:點擊、選取內容等等,而此時 web worker 在后臺運行。
有什么好處?
1:子線程計算不會阻塞主線程
2:充分利用CPU!
OK,現在來具體實現多線程!
var oW = new Worker('a.js');
//a.js是子線程js文件,代表的是后臺需要處理的地址
oW.postMessage(12);
//在多線程里,利用postMessage來傳輸數據
下面來寫a.js文件。
//用onmessage事件來接收數據,ev.data代表的是接收過來的數據,這里指主線程發過來的12
self.onmessage=function(ev){
//self指全局worker對象(用this也行)
alert(ev.data)
}
這里需要注意的是上面在子線程里用alert是錯誤的。
安全與限制
在worker的代碼中,不要訪問一些重要的JavaScript對象,如document、window、console、parent,更重要的是不要訪問DOM對象。也許不用DOM元素以至不能更新頁面元素聽上去有點嚴格,但是這是一個重要的安全設計決定。
想象一下,如果眾多線程都試著去更新同一個元素那就是個災難。所以,web worker需要處在一個嚴格的并線程安全的環境中。
正如之前所說,你可以通過worker處理數據,并將結果返回主線程,進而更新DOM元素。盡管它們不能訪問一些重要的JavaScript對象,但是它們可以調用一些函數,如setTimeout()/clearTimeout()、setInterval()/clearInterval()、navigator等等,也可以訪問XMLHttpRequest和localStorge對象。
為了能和服務器交互,worker必須遵守同源策略(same-origin policy)(譯注:可參考國人文章同源策略)。比如,位于http://www.example.com/ 內的腳本文件不能訪問https://www.example.com 的腳本。盡管域名相同,但同源策略要求端口也必須一致。通常,這不會成為一個很大的問題。但是你很有可能會同一個域名編寫worker和client,所以知道這點對你總是有所幫助。
整體Worker具體步驟就是這樣的 ,下面完整寫一個主線程發給子線程一個數組數據,然后子線程處理數據數據并發回主線程的代碼。
//開啟了子線程
var arr = [12,5,8];
var oW = new Worker('d.js');
//發送
oW.postMessage(arr)
oW.onmessage = function (ev) {
alert(ev.data);//666,5,8
};
console.log(arr);//12,5,8
//主線程和子線程有它們各自的獨立空間,信息主要是來回交換而不是共享。
d.js文件
self.onmessage = function(ev){
ev.data[0] = 666;
this.postMessage(ev.data);
};
當然,Workers不是簡簡單單修改一個數組這么簡單了,那么什么時候可以用到多線程呢?
worker的實際發生場景可能是,你需要處理一個同步的第三方接口,于是主線程需要等待結果再進行下一步操作。這種情況下,你可以生成一個worker,由它代理,異步完成此任務。
Web worker在輪詢情況下也非常適用,你可以在后臺不斷查詢目標,并在有新數據時向主線程發送消息。
你也許遇到需要向服務端返回大量的數據的情況。通常,處理大量數據會消極影響程序的響應能力,然后導致不良用戶體驗。更優雅的辦法是將處理工作分配給若干worker,由它們處理不重疊的數據。
還有應用場景會出現在通過多個web worker分析音頻或視頻的來源,每個worker針對專項問題。
譯注:本人不是什么大牛,只是一個一直在學習的小程序員,如果文章內容當中有什么不對的地方請與我討論,共同進步!