webworker的作用
讓web應用程序具備多線程處理能力,常用來處理一些比較耗時的任務。假設我們的應用上有個純前端實現的馬賽克濾鏡,我們知道圖像處理,尤其是大圖片的處理通常是比較耗費時的,隨時都有可能讓你的頁面卡個幾秒,這期間UI線程會被阻塞,這意味着用戶需要對着一個無法進行任何交互的頁面抓狂,這是無法容忍的。這個時候,webworker就發揮它的用處了,圖像處理神馬的后台悄悄進行就行了,用戶可以繼續瀏覽器美圖神馬的(奸笑),時間到,打了馬賽克的妹子圖片就呈現在用戶面前了
簡單例子
下面的demo涉及兩個文件,分別是demo.html、worker.js。代碼很簡單,但已經包含了webworker最重要的幾個內容,細節在后面再展開:
- worker創建:new Worker(XX)
- 消息發送:postMessage
- worker事件:消息接收(message)、出錯處理(error)
- worker終止:terminate
demo.html里面的代碼:
var worker = new Worker('worker.js');
worker.onmessage = function(evt){
alert('消息收到啦:'+ evt.data);
worker.terminate();
};
worker.onerror = function(e){
alert('demo出錯了!出錯原因是:' + e.message);
worker.terminate();
};
worker.postMessage('這是webworker的demo!');
worker.js里面的代碼:
this.onmessage = function(evt){
postMessage(evt.data +'--worker.js里的附加信息');
};
demo演示內容:
- demo.html里創建一個worker W,W加載worker.js,並向其發送消息:這是'webworker的demo!'
- worker.js 收到W傳給它的消息,並在該消息末尾加上'--worker.js里的附加信息'后,再回傳給W
- W收到worker.js回傳的消息,彈窗顯示,然后把自己給終止掉
最終你會看到
消息收到啦:這是webworker的demo!--worker.js里的附加信息
常用API等簡單介紹
1. worker創建
注意:引號里的url地址可以為絕對地址,或相對地址,但必須同源
var worker = new Worker('worker.js');
2. 常用API
possMessage(data)
data理論上可以為任意值,但保險起見最好還是傳字符串,接收方需注冊message事件老接收消息,如demo.html中
var worker = new Worker('worker.js');
terminate()
終止worker,此后無法再利用其進行消息傳遞等。需要注意:worker不會自行終止,一旦terminate,無法重新啟用,只能另行創建。如demo.html中
worker.terminate();
3. 事件
message
一旦有消息發送,則會觸發。消息的發送是雙向的,消息的內容可通過data獲取,如demo.html中,evt.data即為worker.js中傳遞過來的消息內容:
worker.onmessage = function(evt){
alert('消息收到啦:'+ evt.data);
worker.terminate();
};
error
出錯處理,比如worker.js中出現語法錯誤、運行時錯誤之類的,就會觸發,錯誤信息可通過e.message獲得,如demo.html中
worker.onerror = function(e){
alert('demo出錯了!出錯原因是:' + e.message);
worker.terminate();
};
worker的上下文
剛剛接觸web worker的童鞋,對於這點可能有些疑惑。我們可以先用下面這個小小的例子簡單說明一下。還是之前的worker.js,只不過在最開頭的時候加上了一句alert('hello world');
alert('hello'); //額外添加的語句
this.onmessage = function(evt){
postMessage(evt.data +'--worker.js里的附加信息');
};
於是,你會看到下面的彈窗內容
demo出錯了!出錯原因是:Uncaught ReferenceError: window is not defined
從上面的出錯提示可以猜想:worker.js執行的上下文,與demo.html執行時的上下文並不相同,最頂層的對象的對象並不是window,無法訪問window、與window相關的DOM API,但是可以與setTimeout、setInterval等協作。
woker.js執行的全局上下文,是個叫做WorkerGlobalScope的東東,它具有屬性/方法:
self
指向WorkerGlobalScope
inmoprScripts(XX[,XX, XX…])
加載外部腳本文件,理論上是按照加載它們的順序執行(僅僅是理論上),且執行上下文與當前執行上下文一致,比如在worker.js里面
importScripts('subworker.js');
importScripts('a.js', 'b.js', 'c.js');
那么理論上,subworker.js、a.js、b.js、c.js應該是hi順序執行的,這里就不舉具體例子了。
close()
關閉當前線程,與terminate作用類似
location
返回當前worker的location信息,location.href為當前worker創建時指向的文件絕對路徑
setTimeout/setInterval
沒什么好介紹的
子worker的創建
可在當前woker環境下,通過new Worker(XX)方式創建子worker,需要注意的有以下幾點:
- 子worker的路徑必須與父網頁同源
- 子worker的路徑相對於父worker解析,而不是父網頁
- webkit(chrome 25,safari 6)內核的瀏覽器尚不支持子worker,無力吐槽
需要注意的坑
前端科普文必然有的一塊內容,腫么突然有點心酸~~Fraky大大已經總結了不少,就偷懶下了,鏈接如下可猛點擊:http://www.cnblogs.com/_franky/archive/2010/11/23/1885773.html
待解決
- 調試問題:chrome最新版本也仍不支持子線程調試??(已支持,開發者工具-source-workers)
