1.JS單線程
說起Web Workers袖瞻,首先必須了解因為JS運行在瀏覽器中辙诞,是單線程的,每個window一個JS線程,既然是單線程的骗村,在某個特定的時刻只有特定的代碼能夠被執(zhí)行嫌褪,并阻塞其它的代碼。而瀏覽器是事件驅動的(Event driven)胚股,瀏覽器中很多行為是異步(Asynchronized)的渔扎,會創(chuàng)建事件并放入執(zhí)行隊列中。javascript引擎是單線程處理它的任務隊列信轿,你可以理解成就是普通函數(shù)和回調(diào)函數(shù)構成的隊列。當異步事件發(fā)生時残吩,如mouse click, a timer firing, or an XMLHttpRequest completing(鼠標點擊事件發(fā)生财忽、定時器觸發(fā)事件發(fā)生、XMLHttpRequest完成回調(diào)觸發(fā)等)泣侮,將他們放入執(zhí)行隊列即彪,等待當前代碼執(zhí)行完成。
2.Web Workers(多線程)
什么是Web Worker活尊?
web worker 是運行在后臺的 JavaScript隶校,獨立于其他腳本,不會影響頁面的性能蛹锰。您可以繼續(xù)做任何愿意做的事情:點擊深胳、選取內(nèi)容等等,而此時 web worker 在后臺運行铜犬。
有什么好處舞终?
1:子線程計算不會阻塞主線程
2:充分利用CPU!
OK癣猾,現(xiàn)在來具體實現(xiàn)多線程敛劝!
var oW = new Worker('a.js');
//a.js是子線程js文件纷宇,代表的是后臺需要處理的地址
oW.postMessage(12);
//在多線程里夸盟,利用postMessage來傳輸數(shù)據(jù)
下面來寫a.js文件。
//用onmessage事件來接收數(shù)據(jù)像捶,ev.data代表的是接收過來的數(shù)據(jù)上陕,這里指主線程發(fā)過來的12
self.onmessage=function(ev){
//self指全局worker對象(用this也行)
alert(ev.data)
}
這里需要注意的是上面在子線程里用alert是錯誤的。
安全與限制
在worker的代碼中作岖,不要訪問一些重要的JavaScript對象唆垃,如document、window痘儡、console辕万、parent,更重要的是不要訪問DOM對象。也許不用DOM元素以至不能更新頁面元素聽上去有點嚴格渐尿,但是這是一個重要的安全設計決定醉途。
想象一下,如果眾多線程都試著去更新同一個元素那就是個災難砖茸。所以隘擎,web worker需要處在一個嚴格的并線程安全的環(huán)境中。
正如之前所說凉夯,你可以通過worker處理數(shù)據(jù)盛龄,并將結果返回主線程圣拄,進而更新DOM元素。盡管它們不能訪問一些重要的JavaScript對象,但是它們可以調(diào)用一些函數(shù)钟些,如setTimeout()/clearTimeout()克婶、setInterval()/clearInterval()穷当、navigator等等昔善,也可以訪問XMLHttpRequest和localStorge對象。
為了能和服務器交互人柿,worker必須遵守同源策略(same-origin policy)(譯注:可參考國人文章同源策略)柴墩。比如,位于http://www.example.com/ 內(nèi)的腳本文件不能訪問https://www.example.com 的腳本凫岖。盡管域名相同江咳,但同源策略要求端口也必須一致。通常哥放,這不會成為一個很大的問題扎阶。但是你很有可能會同一個域名編寫worker和client,所以知道這點對你總是有所幫助婶芭。
整體Worker具體步驟就是這樣的 东臀,下面完整寫一個主線程發(fā)給子線程一個數(shù)組數(shù)據(jù),然后子線程處理數(shù)據(jù)數(shù)據(jù)并發(fā)回主線程的代碼犀农。
//開啟了子線程
var arr = [12,5,8];
var oW = new Worker('d.js');
//發(fā)送
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不是簡簡單單修改一個數(shù)組這么簡單了赁濒,那么什么時候可以用到多線程呢?
worker的實際發(fā)生場景可能是孟害,你需要處理一個同步的第三方接口拒炎,于是主線程需要等待結果再進行下一步操作。這種情況下挨务,你可以生成一個worker击你,由它代理玉组,異步完成此任務。
Web worker在輪詢情況下也非常適用丁侄,你可以在后臺不斷查詢目標惯雳,并在有新數(shù)據(jù)時向主線程發(fā)送消息。
你也許遇到需要向服務端返回大量的數(shù)據(jù)的情況鸿摇。通常石景,處理大量數(shù)據(jù)會消極影響程序的響應能力,然后導致不良用戶體驗拙吉。更優(yōu)雅的辦法是將處理工作分配給若干worker潮孽,由它們處理不重疊的數(shù)據(jù)。
還有應用場景會出現(xiàn)在通過多個web worker分析音頻或視頻的來源筷黔,每個worker針對專項問題恩商。
譯注:本人不是什么大牛,只是一個一直在學習的小程序員必逆,如果文章內(nèi)容當中有什么不對的地方請與我討論,共同進步揽乱!