web worker
背景
眾所周知javascript是單線程的,同一時間內只能做一件事情。
這是十分必要的,設想,如果js是多線程的。有個dom元素兩個線程同時做了改變,一個display:none,另一個display:block,這樣讓瀏覽器就無所適從了。出於此種考慮,單線程的js就這樣一直延續下來,但是凡事必有兩面性,雖然單線程保證了一些ui操作的可行性,但一些比較耗時任務, 單線程的js執行起來就會有一些不太好的體驗。好一點是一直loading的提示條,更甚的可能連提示都沒有,即所謂的假死狀態。web worker就應運而生了。
什么是web worker
Web Workers 使得一個Web應用程序可以在與主執行線程分離的后台線程中運行一個腳本操作。把那些耗時的操作放在該線程中執行,這樣就避免了主線程即UI線程被阻塞。
簡而言之,就是在主線程即負責ui交互的js之外,新開一個后台腳本負責費時操作的執行。本來可能阻塞UI的操作,就直接不與dom打交道避免長時間阻塞,執行完成之后通知主線程即可。
web worker上下文
正如前面提到的,web worker誕生的目的在於解決耗時操作對ui交互的影響,所以worker不能訪問和操作dom的,如果有這個能力那么上面提到同時操作的問題就又會出現了。
worker中的上下文和主線程js的上下文對象是不同的,window不是它的頂層對象,所以window相關的一些方法如alert等時不能使用的,還有dom也是不能訪問的。不過基本的方法。例如console.log、setTimeout等可以訪問。
worker常見可用API和屬性
- setInterval/clearInterval
- setTimeout/setInterval
- Cache
- Console API
- CustomEvent
- Fetch
- FileReader/FileReaderSync
- FormData
- Promise
- WebSocket
- XMLHttpRequest
等,更多請查看Functions and classes available to Web Workers
如何創建 web worker
創建一個web worker 十分簡單,只需要new worker(path),path為worker文件的路徑。如下面代碼所示:
// 檢測是否支持window.Worker
if (window.Worker) {
// 指定worker文件路徑,據此創建Worker
var worker = new Worker('./ww.js')
// 監控message,當收到worker信息時執行
worker.onmessage = function (e) {
var div = document.querySelector('#root')
div.innerHTML = e.data
}
}
通信機制
主線程js與worker 線程之間通信機制比較簡單。兩者通過postMessage和onmessage來傳遞信息。
- postMessage:發送信息,主線程js和worker都可以通過該方法發送消息,不過主線程中該方法是worker的方法,worker中可以直接調用。
- onmessage: 接受信息的事件,后面跟相應回調。
具體代碼如下:
/* 主線程js發送接受消息 */
// 指定worker文件路徑,據此創建Worker
var worker = new Worker('./ww.js')
var isFirst = true
// 監聽message事件,當收到worker信息時執行
worker.onmessage = function(e){
var div = document.querySelector('#root')
div.innerHTML = e.data
// 首次執行,發送信息給worker
isFirst && worker.postMessage('來自主線程的消息')
isFirst =false
}
worker :
/* worker 接受發送消息 */
// 2s之后執行循環,並發送
postMessage('執行結果' + j + '執行結束時間' + new Date().toLocaleTimeString())
onmessage = function (e) {
console.log(e)
postMessage(e.data)
}
更多worker
除了上面提到的worker之外還要一下幾種worker。
- Shared Workers 共享worker。可被對多個腳本運行在不同的窗體,例如IFrames等, 只要這些workers處於同一域名。共享worker 比專用 worker 稍微復雜一點 — 腳本必須通過活動端口進行通訊。詳情請見SharedWorker。
- Service Workers 一般作為web應用程序、瀏覽器和網絡(如果可用)之前的代理服務器。目前比較熱的PWA就是基於該技術實現的。當然也不僅僅用於緩存資源二用,作為代理可以用其實現更多的功能,例如訪問推送通知和后台同步等。
- Chrome Workers 是一種僅適用於firefox的worker。詳情請見ChromeWorker
- 音頻 Workers可以在網絡worker上下文中直接完成腳本化音頻處理.
參考文檔
結束語
至此關於web worker 的簡單介紹就結束了,前段時間看了下websocket和PWA所以就一起看一下web worker和service worker。拋磚引玉,希望大家共同進步,更多請查看我的實例demo