瀏覽器端js是單線程執行,所以當js執行高負載運算時,UI渲染就會阻塞,頁面就會出現卡頓,用戶體驗就不是很好 js為此也提供了非同步操作,例如: 定時器(setTimeout 和 setInterval),Ajax請求等,但非同步終究還是單線程,不能從根本上解決問題,像setTimeout並不能拿到正確 ...
瀏覽器端js是單線程執行,所以當js執行高負載運算時,UI渲染就會阻塞,頁面就會出現卡頓,用戶體驗就不是很好
js為此也提供了非同步操作,例如: 定時器(setTimeout 和 setInterval),Ajax請求等,但非同步終究還是單線程,不能從根本上解決問題,像setTimeout並不能拿到正確的值,因為執行的時候將該任務放到主線程執行,只有當前面的任務執行完才開始執行,所以即使設置時間為0,也並不一定立刻執行
所以HTML5標準添加了Web Worker,worker允許一段js程式運行在主線程之外的線程,子線程與主線程互不幹擾,當子線程的代碼執行完成,將結果返回給主線程,主線程接收到相應結果後再做對應處理,當有一些計算密集型或高延遲的任務就可以交給worker子線程來負擔,主線程就不會阻塞
worker是window對象的一個方法,一個worker對象可通過構造函數(window.worker())來創建,創建對象時,需要傳給構造函數一個js文件,該文件包含了放到子線程中運行的代碼
worker通過postMessage()和onmessage = () => {} 來進行通信,主線程和子線程通信是雙向的,都有可以發送和接收信息,postMessage傳遞的數據都是拷貝傳遞(ArrayBuffer除外)
子線程運行耗損系統資源,所以當執行完畢後,我們可以手動關閉子線程
在主線程中關閉: worker.terminate()
在子線程中關閉: self.close() (在子線程中window需改寫成self,下文有解釋)
worker限制
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