標籤:http java 使用 os io strong 檔案 資料
介紹
通過使用WebWorker,我們可以在瀏覽器後台運行Javascript,而不佔用瀏覽器自身線程。WebWorker可以提高應用的總體效能,並且提升使用者體驗。如果你想在自己的Web應用中使用WebWorker,不妨來瞭解一下有關WebWorker的7件事。
1.WebWorker可以讓你在後台運行Javascript
一般來說Javascript和頁面的UI會共用一個線程,所以當點擊一個按鈕開始運行Javascript後,在這段代碼運行完畢之前,頁面是無法響應使用者操作的,換句話來說就是被“凍結”了。而這段代碼可以交給WebWorker在後台運行,那麼頁面在Javascript運行期間依然可以響應使用者操作。後台會啟動一個worker線程來執行這段代碼,使用者可以建立多個worker線程。所以你可以在前台做一些小規模分散式運算之類的工作,不過WebWorker有以下一些使用限制:
- WebWorker無法訪問DOM節點;
- WebWorker無法訪問全域變數或是全域函數;
- WebWorker無法調用alert()或者confirm之類的函數;
- WebWorker無法訪問window、document之類的瀏覽器全域變數;
不過WebWorker中的Javascript依然可以使用setTimeout(),setInterval()之類的函數,也可以使用XMLHttpRequest對象來做Ajax通訊。
2.有兩種WebWorker
Webworkers可分為兩種類型:專用線程dedicatedwebworker,以及共用線程sharedwebworker。Dedicatedwebworker隨當前頁面的關閉而結束;這意味著Dedicatedwebworker只能被建立它的頁面訪問。與之相對應的Sharedwebworker可以被多個頁面訪問。在Javascript代碼中,“Work”類型代表Dedicatedwebworker,而“SharedWorker”類型代表Sharedwebworker。
在絕大多數情況下,使用Dedicatedwebworker就足夠了,因為一般來說在webworker中啟動並執行代碼是專為當前頁面服務的。而在一些特定情況下,webworker可能啟動並執行是更為普遍性的代碼,可以為多個頁面服務。在這種情況下,我們會建立一個共用線程的Sharedwebworker,它可以被與之相關聯的多個頁面訪問,只有當所有關聯的的頁面都關閉的時候,該Sharedwebworker才會結束。相對Dedicatedwebworker,sharedwebworker稍微複雜些。
3.“Worker”對象代表DedicatedWebWorker
現在來看如何使用Dedicatedwebworker。下面的例子中用到了jQuery以及Modernizr作為Javascript庫,然後往HTML頁面中加入以下代碼:
[html]
- <!DOCTYPEhtml>
- <html>
- <head>
- <title></title>
- <scripttype="text/javascript"src="script/modernizr.js"></script>
- <scripttype="text/javascript"src="script/jquery-2.0.0.js"></script>
- <scripttype="text/javascript">
- $(document).ready(function(){
- if(!Modernizr.webworker){
- alert("Thisbrowserdoesn‘tsupportWebWorker!");
- return;
- }
- $("#btnStart").click(function(){
- varworker=newWorker("script/lengthytask.js");
- worker.addEventListener("message",function(evt){
- alert(evt.data);
- },false);
- worker.postMessage(10000)
- });
- });
- </script>
- </head>
- <body>
- <form>
- <inputtype="button"id="btnStart"value="StartProcessing"/>
- </form>
- </body>
- </html>
這個HTML頁面中有個按鈕,點擊後會運行一個Javascript檔案。上面的代碼中首先檢測當前瀏覽器是否支援WebWorker,不支援的話,就跳出提醒資訊。
按鈕的點擊事件中建立了Worker對象,並給它指定了Javascript指令檔——lengthytask.js(稍後會有代碼),並且給Worker對象綁定了一個“message”事件。該事件會在後台代碼(lengthytask.js)向頁面返回資料時觸發。“message”事件可以通過event.data來擷取後台代碼傳回的資料。最後,postMessage方法正式執行lengthytask.js,該方法還可以向後台代碼傳遞參數,後台代碼同樣通過message事件擷取該參數。
下面是lengthytask.js主要包含的代碼:
[javascript]
- addEventListener("message",function(evt){
- vardate=newDate();
- varcurrentDate=null;
- do{
- currentDate=newDate();
- }while(currentDate-date<evt.data);
- postMessage(currentDate);
- },false);
以上代碼在後台監聽message時間,並擷取頁面傳來的參數:10000;這裡實際上是一個計時函數:在message事件被觸發10000毫秒之後,把結果(currentDate)傳給頁面。
所以當點擊“StartProcessing”按鈕,頁面會在10秒鐘後把當時的時刻alert出來。在這10秒鐘內頁面依然可以響應滑鼠鍵盤事件。
4.“SharedWorker”對象代表SharedWebWorker
前面的代碼使用的是dedicatedwebworker。這一節會用sharedwebworker代替dedicatedwebworker,來區別兩者的不同。下面是同一個例子的sharedwebworker版本:
[javascript]
- addEventListener("message",function(evt){
- vardate=newDate();
- varcurrentDate=null;
- do{
- currentDate=newDate();
- }while(currentDate-date<evt.data);
- postMessage(currentDate);
- },false);
請注意加黑的代碼,這裡建立了一個SharedWorker對象,並把message事件綁定在sharedworker的port對象上;同樣由port對象發起postMessage,開始執行後台代碼sharedlengthytask.js。
下面是sharedlengthytask.js的主要代碼:
[javascript]
- varport;
- addEventListener("connect",function(evt){
- port=evt.ports[0];
- port.addEventListener("message",function(evt){
- vardate=newDate();
- varcurrentDate=null;
- do{
- currentDate=newDate();
- }while(currentDate-date<evt.data);
- port.postMessage(currentDate);
- },false);
- port.start();
- },false);
使用SharedWorker對象的後台代碼需要綁定connect和message事件,connect事件會在頁面上的port被start時觸發。之後的message事件的回呼函數與之前的基本相同,最後port調用postMessage方法把結果傳回給頁面。
5.WebWorker使用XMLHttpRequest與服務端通訊
有些情況下,webworker還需要與伺服器進行互動。比如頁面可能需要處理來自資料庫中的資訊,我們就需要使用Ajax技術與伺服器互動,下面程式碼封裝含了webworker如何從服務端擷取資料:
[javascript]
- addEventListener("message",function(evt){
- varxhr=newXMLHttpRequest();
- xhr.open("GET","lengthytaskhandler.ashx");
- xhr.onload=function(){
- postMessage(xhr.responseText);
- };
- xhr.send();
- },false);
上面的代碼向服務端的asp.net服務lengthytaskhandler.ashx發出GET請求。並註冊了擷取資料後的onload事件。下面的代碼是服務端的lengthytaskhandler.ashx:
[csharp]
- namespaceWebWorkerDemo
- {
- publicclassLengthyTaskHandler:IHttpHandler
- {
- publicvoidProcessRequest(HttpContextcontext)
- {
- System.Threading.Thread.Sleep(10000);
- context.Response.ContentType="text/plain";
- content.Response.Write("Processingsuccessful!");
- }
- publicboolIsReusable
- {
- get
- {
- returnfalse;
- }
- }
- }
- }
如你所見,ProcessRequest類比了一個長時間啟動並執行任務,並返回了“Processingsuccessful!”的訊息。
6.通過Error事件捕捉錯誤資訊
當我們把越來越複雜的邏輯加到WebWorker裡時,錯誤處理機制是必不可少的。而WebWorker恰恰提供了error事件,供開發人員捕捉錯誤資訊。下面的代碼展示了如何綁定error事件:
[javascript]
- $("#btnStart").click(function(){
- varworker=newWorker("scripts/lengthytask.js");
- worker.addEventListener("error",function(evt){
- alert("Line#"+evt.lineno+"-"+evt.message+"in"+evt.filename);
- },false);
- worker.postMessage(10000);
- });
如上可見,Worker對象可以綁定error事件;而且evt對象中包含錯誤所在的代碼檔案(evt.filename)、錯誤所在的程式碼數(evt.lineno)、以及錯誤資訊(evt.message)。
7.通過terminate()方法終止WebWorker
有些情況下,我們可能需要強制終止執行中的WebWorker。Worker對象提供了terminate()來終止自身執行任務,被終止的Worker對象不能被重啟或重用,我們只能建立另一個Worker執行個體來執行新的任務。
總結
WebWorker可以在後台執行指令碼,而不會阻塞頁面互動。Worker對象分為兩種:專用式WebWorker和共用式WebWorker:專用式的WebWorker只能被當個頁面使用,而共用式的WebWorker可以在被多個頁面使用。另外,本文還介紹了WebWorker的錯誤處理機制,以及使用Ajax與服務端互動。