HTML5新特性之線程

簡(jiǎn)單背景介紹

JavaScripts 本身是一種單線程設(shè)計(jì),無(wú)法在同一時(shí)刻并行的運(yùn)行多個(gè)腳本。瀏覽器處理的每一個(gè)任務(wù)都是通過(guò)串行的方式進(jìn)行處理。
通常當(dāng)使用setTimeout()和setInterval()這樣的函數(shù)時(shí),可能會(huì)產(chǎn)生多個(gè)線程獨(dú)立于JavaScript主線程同時(shí)運(yùn)行的錯(cuò)覺(jué),但事實(shí)上,這些函數(shù)其實(shí)都被加入了主線程使用得同一個(gè)事件循環(huán)里。這種方式有一個(gè)缺點(diǎn),一旦使用任何會(huì)導(dǎo)致阻塞的函數(shù),就會(huì)使瀏覽器失去響應(yīng)。
如Ajax中使用的XMLHttpRequest對(duì)象有同步和異步兩種模式。異步模式使用的頻率要遠(yuǎn)遠(yuǎn)高于同步模式,因?yàn)橥降恼?qǐng)求會(huì)牽制整個(gè)線程,在請(qǐng)求返回前會(huì)阻塞所有后續(xù)指令的執(zhí)行。這會(huì)導(dǎo)致所有與頁(yè)面的交互行為全部失效,表現(xiàn)出來(lái)的效果就是頁(yè)面雖然顯示出來(lái)了,但是會(huì)沒(méi)有反應(yīng)。

Web Workers

Web Workers通過(guò)引入類似線程的機(jī)制是這種問(wèn)題得到有效的解決。
使用Web Workers創(chuàng)建一個(gè)工作線程就是能夠簡(jiǎn)單地加載一段腳本并在后臺(tái)線程中執(zhí)行。 一個(gè)運(yùn)行在工作線程中的腳本是無(wú)法影響或阻塞主線程的,這意味著可以一邊進(jìn)行cpu密集型的處理,同時(shí)用戶繼續(xù)運(yùn)行游戲或者應(yīng)用。

分類

專用線程

  • 專用型worker與創(chuàng)建它的腳本連接在一起,它可以與其他的worker或是瀏覽器組件通信,但是他不能與DOM通信。專用的含義,就是這個(gè)線程一次只處理一個(gè)需求。專用線程在除了IE外的各種主流瀏覽器中都實(shí)現(xiàn)了,可以放心使用。
  • 專用線程只適合當(dāng)前客戶端使用,與其他客戶端無(wú)關(guān)聯(lián),適用于本客戶端內(nèi)(本瀏覽器)的多線程使用。

共享線程

  • 共享線程適用于多個(gè)客戶端(多個(gè)瀏覽器)之間進(jìn)行數(shù)據(jù)交互和控制,但是html5中沒(méi)有類似鎖機(jī)制,所以安全性存在一定問(wèn)題。
  • 共享線程可以有多個(gè)連接。用于解決多連接并發(fā)的問(wèn)題。它們并不是綁定于一個(gè)HTML頁(yè)面的。如果你在同一個(gè)瀏覽器上打開(kāi)了同一個(gè)網(wǎng)站的頁(yè)面,這些頁(yè)面都可以訪問(wèn)其中任意頁(yè)面創(chuàng)建的共享工作線程。

創(chuàng)建專用線程

  • 創(chuàng)建一個(gè)工作線程需要使用Worker( )構(gòu)造函數(shù),把需要在線程中執(zhí)行的JavaScript文件的文件名傳給構(gòu)造函數(shù)就可以了。
 var worker = new Worker("myworker.js");
  • 然后在實(shí)例上監(jiān)聽(tīng)onmessage事件,來(lái)獲取消息。
worker.onmessage = function(event){
    //從工作線程獲取消息
}
  • 或者使用監(jiān)聽(tīng)方法
worker.addEventListener("message",function(event){
    //從工作線程獲取消息
},false);
  • 兩種方式下,都可以在event對(duì)象的data屬性中找到消息數(shù)據(jù)。數(shù)據(jù)已經(jīng)自動(dòng)地由JSON格式解碼為原始格式,因此數(shù)據(jù)結(jié)構(gòu)沒(méi)有任何改變。
  • 最后通過(guò)調(diào)用postMessage( )函數(shù)在不同線程中傳遞數(shù)據(jù)。

    工作線程和它們的父線程通過(guò)一組公共的消息API進(jìn)行通信。數(shù)據(jù)都是通過(guò)字符串的形式進(jìn)行傳遞的,但是這并不意味著你只能發(fā)送字符串形式的而消息。如果你發(fā)送一些復(fù)雜的結(jié)構(gòu)體,比如對(duì)象或者數(shù)組,它們將自動(dòng)轉(zhuǎn)換成JSON格式。但是DOM元素是不能轉(zhuǎn)換成JSON的,因此其不能與DOM通信。

  • 當(dāng)你使用工作線程完成了既定的工作時(shí),需要銷(xiāo)毀線程。

    在線程內(nèi)部,使用close方法線程自己銷(xiāo)毀自己。在線程外部的主線程中,使用線程實(shí)例的terminate方法銷(xiāo)毀線程。

worker.terminate( );
  • 使用其他腳本

    工作線程可以使用全局方法importScripts來(lái)加載和使用其他的域內(nèi)腳本文件或者類庫(kù)。如:

    importScripts();                        
    importScripts('foo.js');                
    importScripts('foo.js', 'bar.js'); 
    
  • 線程嵌套

    在工作線程中還可以在創(chuàng)建子線程。

  • 同步問(wèn)題

    Worker沒(méi)有鎖的機(jī)制,多線程的同步問(wèn)題只能靠代碼來(lái)解決(比如定義信號(hào)變量)。

共享線程與專用線程

共享線程可以有多個(gè)連接。用于解決多連接并發(fā)的問(wèn)題。它們并不是綁定于一個(gè)HTML頁(yè)面的。如果你在同一個(gè)瀏覽器上打開(kāi)了同一個(gè)網(wǎng)站的頁(yè)面,這些頁(yè)面都可以訪問(wèn)其中任意頁(yè)面創(chuàng)建的共享工作線程。

  • 可以使用 SharedWorker()構(gòu)造函數(shù),創(chuàng)建共享工作線程。

除了腳本的路徑外,這個(gè)構(gòu)造函數(shù)還需要一個(gè)可選的name參數(shù)。如果name參數(shù)沒(méi)有指定會(huì)使用一個(gè)空字符串。如果創(chuàng)建一個(gè)和既有實(shí)例使用相同腳本和名字的共享工作線程,只會(huì)為已存在的線程增加一個(gè)新的連接而并不會(huì)創(chuàng)建一個(gè)全新的線程。

  • 共享線程不像專用工作線程那樣擁有一個(gè)全局的message事件。他們必須來(lái)監(jiān)聽(tīng)connect事件來(lái)獲取新頁(yè)面何時(shí)向共享工作線程創(chuàng)建創(chuàng)建連接。工作線程和創(chuàng)建連接那個(gè)線程之間的通信是基于觸發(fā)message事件的port對(duì)象,利用的是其提供的postMessage( )。必須要調(diào)用port.start( )才能開(kāi)始接收消息。

Web Worker 使用注意:

  1. 同源限制

分配給 Worker 線程運(yùn)行的腳本文件,必須與主線程的腳本文件同源。

  1. DOM 限制

Worker 線程所在的全局對(duì)象,與主線程不一樣,無(wú)法讀取主線程所在網(wǎng)頁(yè)的 DOM 對(duì)象,也無(wú)法使用document、window、parent這些對(duì)象。但是,Worker 線程可以navigator對(duì)象和location對(duì)象。

  1. 通信聯(lián)系

Worker 線程和主線程不在同一個(gè)上下文環(huán)境,它們不能直接通信,必須通過(guò)消息完成。

  1. 腳本限制

Worker 線程不能執(zhí)行alert()方法和confirm()方法,但可以使XMLHttpRequest 對(duì)象發(fā)出 AJAX 請(qǐng)求。

  1. 文件限制

Worker 線程無(wú)法讀取本地文件,即不能打開(kāi)本機(jī)的文件系統(tǒng)(file://),它所加載的腳本,必須來(lái)自網(wǎng)絡(luò)。

Web Worker的兼容性

webworker.png

從圖上看兼容性異常的好,甚至連IE系列都在好幾年前就已經(jīng)支持,但是這個(gè)兼容性只能說(shuō)明能否使用Web Woker,這里的兼容并不能表明能在其中做其他操作。比如標(biāo)準(zhǔn)規(guī)定,可以在子線程做做計(jì)算、發(fā)起XHR請(qǐng)求等,但不能操作DOM對(duì)象,但實(shí)際使用中,F(xiàn)ecth在IE系列(包括Edge)瀏覽器中并不支持,會(huì)直接報(bào)錯(cuò)。

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

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

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