瀏覽器端js是單線程執行,因此當js執行高負載運算時,UI渲染就會阻塞,頁面就會出現卡頓,用戶體驗就不是很好javascript
js爲此也提供了異步操做,例如: 定時器(setTimeout 和 setInterval),Ajax請求等,但異步終究仍是單線程,不能從根本上解決問題,像setTimeout並不能拿到正確的值,由於執行的時候將該任務放到主線程執行,只有當前面的任務執行完纔開始執行,因此即便設置時間爲0,也並不必定馬上執行java
因此HTML5標準添加了Web Worker,worker容許一段js程序運行在主線程以外的線程,子線程與主線程互不干擾,當子線程的代碼執行完成,將結果返回給主線程,主線程接收到相應結果後再作對應處理,當有一些計算密集型或高延遲的任務就能夠交給worker子線程來負擔,主線程就不會阻塞跨域
worker是window對象的一個方法,一個worker對象可經過構造函數(window.worker())來建立,建立對象時,須要傳給構造函數一個js文件,該文件包含了放到子線程中運行的代碼瀏覽器
worker經過postMessage()和onmessage = () => {} 來進行通訊,主線程和子線程通訊是雙向的,都有能夠發送和接收信息,postMessage傳遞的數據都是拷貝傳遞(ArrayBuffer除外)異步
子線程運行耗損系統資源,因此當執行完畢後,咱們能夠手動關閉子線程函數
在主線程中關閉: worker.terminate()post
在子線程中關閉: self.close() (在子線程中window需改寫成self,下文有解釋)url
worker限制spa
1)同源線程
分配給worker子線程運行的腳本文件,必須與主線程的腳本文件同源,包括協議,域名和端口,不支持本地地址(file://);
當使用CDN來存儲js文件時,主線程與子線程就會出現跨域
解決方法: 【1】將子線程的腳本轉換成Blod對象
【2】而後給Blod對象建立一個URL
【3】將這個URL傳給worker的構造函數
示例代碼:
var workerBlob = new Blob(['(' + function +')()'], { type: "text/javascript" });
var url = window.URL.createObjectURL(workerBlob);
var worker = new Worker(url);
2) 訪問
worker子線程所在的全局對象,與主線程不在一個上下文環境,因此沒法讀取主線程所在網頁的DOM,沒法使用document,window,parent這些對象,global指向有變動,window須要改寫成self,不能執行alert()和comfire()的方法,只能讀取部分navigator對象內的數據
3)使用異步
worker子線程中支持js的異步操做,但仍然不能夠跨域
worker的兼容性還不錯,但不兼容IE9