DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> HTML基礎知識 >> HTML5詳解 >> 突襲HTML5之Javascript API擴展1—Web Worker異步執行及相關概述
突襲HTML5之Javascript API擴展1—Web Worker異步執行及相關概述
編輯:HTML5詳解     
Javascript執行機制 
在Html5之前,浏覽器中JavaScript的運行都是以單線程的方式工作的,雖然有多種方式實現了對多線程的模擬(例如:Javascript 中的 setinterval 方法,setTimeout 方法等),但是在本質上程序的運行仍然是由 Javascript 引擎以單線程調度的方式進行的。在 Html5 中引入的工作線程使得浏覽器端的 Javascript 引擎可以並發地執行 Javascript 代碼,從而實現了對浏覽器端多線程編程的良好支持。 

Javascript中的多線程 - WebWorker 
Html5 中的 Web Worker 可以分為兩種不同線程類型,一個是專用線程 Dedicated Worker,一個是共享線程 Shared Worker。兩種類型的線程各有不同的用途。 
專用型web worker 
專用型worker與創建它的腳本連接在一起,它可以與其他的worker或是浏覽器組件通信,但是他不能與DOM通信。專用的含義,我想就是這個線程一次只處理一個需求。專用線程在除了IE外的各種主流浏覽器中都實現了,可以放心使用。 
創建線程 
創建worker很簡單,只要把需要在線程中執行的JavaScript文件的文件名傳給構造函數就可以了。 
線程通信 
在主線程與子線程間進行通信,使用的是線程對象的postMessage和onmessage方法。不管是誰向誰發數據,發送發使用的都是postMessage方法,接收方都是使用onmessage方法接收數據。postMessage只有一個參數,那就是傳遞的數據,onmessage也只有一個參數,假設為event,則通過event.data獲取收到的數據。 
發送JSON數據 
JSON是JS原生支持的東西,不用白不用,復雜的數據就用JSON傳送吧。例如: 

復制代碼代碼如下:www.mb5u.com
postMessage({'cmd': 'init', 'timestamp': Date.now()}); 

處理錯誤 
當線程發生錯誤的時候,它的onerror事件回調會被調用。所以處理錯誤的方式很簡單,就是掛接線程實例的onerror事件。這個回調函數有一個參數error,這個參數有3個字段:message - 錯誤消息;filename - 發生錯誤的腳本文件;lineno - 發生錯誤的行。 
銷毀線程 
在線程內部,使用close方法線程自己銷毀自己。在線程外部的主線程中,使用線程實例的terminate方法銷毀線程。 
下面從一個例子看線程的基本操作: 
Html代碼: 

復制代碼代碼如下:www.mb5u.com
<!DOCTYPE Html> 
<Html> 
<head> 
<meta http-equiv="Content-Type" content="text/Html; charset=utf-8" /> 
<title>web worker fibonacci</title> 
<script type="text/Javascript"> 
onload = function(){ 
var worker = new Worker('fibonacci.JS'); 
worker.onmessage = function(event) { 
console.log("Result:" + event.data); 
}; 
worker.onerror = function(error) { 
console.log("Error:" + error.message); 
}; 
worker.postMessage(40); 

</script> 
</head> 
<body> 
</body> 
</Html> 

腳本文件fibonacci.JS代碼: 

復制代碼代碼如下:www.mb5u.com
//fibonacci.JS 
var fibonacci = function(n) { 
return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2); 
}; 
onmessage = function(event) { 
var n = parseInt(event.data, 10); 
postMessage(fibonacci(n)); 
}; 

把它們放到相同的目錄,運行頁面文件,查看控制台,可以看到運行的結果。 
這裡還有一點,在主線程中,onmessage事件可以使用另外一種方式掛接: 

復制代碼代碼如下:www.mb5u.com
worker.addEventListener('message', function(event) { 
console.log("Result:" + event.data); 
}, false); 

個人覺得很麻煩,不如用onmessage直接。 
使用其他腳本文件 
工作線程可以使用全局方法importScripts來加載和使用其他的域內腳本文件或者類庫。例如下面都是合法的使用方式: 

復制代碼代碼如下:www.mb5u.com
importScripts();/* imports nothing */ 
importScripts('foo.js'); /* imports just "foo.JS" */ 
importScripts('foo.js', 'bar.JS');/* imports two scripts */ 

導入以後,可以直接使用這些文件中的方法。看一個網上的小例子: 

復制代碼代碼如下:www.mb5u.com
/** 
* 使用 importScripts 方法引入外部資源腳本,在這裡我們使用了數學公式計算工具庫 math_utilitIEs.JS 
* 當 JavaScript 引擎對這個資源文件加載完畢後,繼續執行下面的代碼。同時,下面的的代碼可以訪問和調用 
* 在資源文件中定義的變量和方法。 
**/ 
importScripts('math_utilitIEs.JS'); 
onmessage = function (event) 

var first = event.data.first; 
var second = event.data.second; 
calculate(first,second); 
}; 
function calculate(first,second) { 
//do the calculation work 
var common_divisor=divisor(first,second); 
var common_multiple=multiple(first,second); 
postMessage("Work done! " + 
"The least common multiple is " + common_divisor + 
" and the greatest common divisor is "+common_multiple); 


網上也有網友想到了利用這裡的importScripts方法解決資源預加載的問題(浏覽器預先加載資源,而不會對資源進行解析和執行),道理也很簡單。 
線程嵌套 
在工作線程中還可以在創建子線程,各種操作還是一樣的。 
同步問題 
Worker沒有鎖的機制,多線程的同步問題只能靠代碼來解決(比如定義信號變量)。 
共享型SharedWebWorker 
共享型web worker主要適用於多連接並發的問題。因為要處理多連接,所以它的API與專用型worker稍微有點區別。除了這一點,共享型web worker和專用型worker一樣,不能訪問DOM,並且對窗體屬性的訪問也受到限制。共享型web worker也不能跨越通信。 
頁面腳本可以與共享型web worker通信,然而,與專用型web worker(使用了一個隱式的端口通信)稍微有點不同的是,通信是顯式的通過使用一個端口(port)對象並附加上一個消息事件處理程序來進行的。 
在收到web worker腳本的首個消息之後,共享型web worker把一個事件處理程序附加到激活的端口上。一般情況下,處理程序會運行自己的postMessage()方法來把一個消息返回給調用代碼,接著端口的start()方法生成一個有效的消息進程。 
看網上能找到的的唯一個例子:創建一個共享線程用於接收從不同連接發送過來的指令,然後實現自己的指令處理邏輯,指令處理完成後將結果返回到各個不同的連接用戶。 
Html代碼: 

復制代碼代碼如下:www.mb5u.com
<!DOCTYPE Html> 
<Html> 
<head> 
<meta charset="UTF-8"> 
<title>Shared worker example: how to use shared worker in Html5</title> 
<script> 
var worker = new SharedWorker('sharedworker.JS'); 
var log = document.getElementById('response_from_worker'); 
worker.port.addEventListener('message', function(e) { 
//log the response data in web page 
log.textContent =e.data; 
}, false); 
worker.port.start(); 
worker.port.postMessage('ping from user web page..'); 
//following method will send user input to sharedworker 
function postMessageToSharedWorker(input) 

//define a JSon object to construct the request 
var instructions={instruction:input.value}; 
worker.port.postMessage(instructions); 

</script> 
</head> 
<body onload=''> 
<output id='response_from_worker'> 
Shared worker example: how to use shared worker in Html5 
</output> 
send instructions to shared worker: 
<input type="text" autofocus oninput="postMessageToSharedWorker(this);return false;"> 
</input> 
</body> 
</Html> 

腳本文件代碼: 

復制代碼代碼如下:www.mb5u.com
// 創建一個共享線程用於接收從不同連接發送過來的指令,指令處理完成後將結果返回到各個不同的連接用戶。 
var connect_number = 0; 
onconnect = function(e) { 
connect_number =connect_number+ 1; 
//get the first port here 
var port = e.ports[0]; 
port.postMessage('A new connection! The current connection number is ' 
+ connect_number); 
port.onmessage = function(e) { 
//get instructions from requester 
var instruction=e.data.instruction; 
var results=execute_instruction(instruction); 
port.postMessage('Request: '+instruction+' Response '+results 
+' from shared worker...'); 
}; 
}; 
/* 
* this function will be used to execute the instructions send from requester 
* @param instruction 
* @return 
*/ 
function execute_instruction(instruction) 

var result_value; 
//implement your logic here 
//execute the instruction... 
return result_value; 


在上面的共享線程例子中,在主頁面即各個用戶連接頁面構造出一個共享線程對象,然後定義了一個方法 postMessageToSharedWorker 向共享線程發送來之用戶的指令。同時,在共享線程的實現代碼片段中定義 connect_number 用來記錄連接到這個共享線程的總數。之後,用 onconnect 事件處理器接受來自不同用戶的連接,解析它們傳遞過來的指令。最後,定義一個了方法 execute_instruction 用於執行用戶的指令,指令執行完成後將結果返回給各個用戶。 

這裡我們並沒有跟前面的例子一樣使用到了工作線程的 onmessage 事件處理器,而是使用了另外一種方式 addEventListener。實際上,前面已經說過,這兩種的實現原理基本一致,只是在這裡有些稍微的差別,如果使用到了 addEventListener 來接受來自共享線程的消息,那麼就要先使用 worker.port.start() 方法來啟動這個端口。之後就可以像工作線程的使用方式一樣正常的接收和發送消息。 
最後陳述 
線程中能做的事: 
1.能使用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函數。 
2.能使用navigator對象。 
3.能使用XMLHttpRequest來發送請求。 
4.可以在線程中使用Web Storage。 
5.線程中可以用self獲取本線程的作用域。 
線程中不能做的事: 
1.線程中是不能使用除navigator外的DOM/BOM對象,例如window,document(想要操作的話只能發送消息給worker創建者,通過回調函數操作)。 
2.線程中不能使用主線程中的變量和函數。 
3.線程中不能使用有"掛起"效果的操作命令,例如alert等。 
4.線程中不能跨域加載JS。 
線程也是需要消耗資源的,而且使用線程也會帶來一定的復雜性,所以如果沒有充足的理由來使用額外的線程的話,那麼就不要用它。
實用參考
官方文檔:http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.Html
WebWorker分類說明:http://www.w3schools.com/Html5/Html5_webworkers.ASP
模板無憂:http://www.mb5u.com/w3school/Html5/
WebWorker概述:https://developer.mozilla.org/en/Using_web_workers
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved