突襲HTML5之Javascript API擴(kuò)展1—Web Worker異步執(zhí)行及相關(guān)概述
來源:易賢網(wǎng) 閱讀:1249 次 日期:2016-07-22 14:53:04
溫馨提示:易賢網(wǎng)小編為您整理了“突襲HTML5之Javascript API擴(kuò)展1—Web Worker異步執(zhí)行及相關(guān)概述”,方便廣大網(wǎng)友查閱!

HTML5 中的 Web Worker 可以分為兩種不同線程類型,一個是專用線程 Dedicated Worker,一個是共享線程 Shared Worker。兩種類型的線程各有不同的用途,感興趣的朋友可以了解下啊,或許對你有所幫助

Javascript執(zhí)行機(jī)制

在HTML5之前,瀏覽器中JavaScript的運(yùn)行都是以單線程的方式工作的,雖然有多種方式實(shí)現(xiàn)了對多線程的模擬(例如:Javascript 中的 setinterval 方法,setTimeout 方法等),但是在本質(zhì)上程序的運(yùn)行仍然是由 JavaScript 引擎以單線程調(diào)度的方式進(jìn)行的。在 HTML5 中引入的工作線程使得瀏覽器端的 Javascript 引擎可以并發(fā)地執(zhí)行 Javascript 代碼,從而實(shí)現(xiàn)了對瀏覽器端多線程編程的良好支持。

Javascript中的多線程 - WebWorker

HTML5 中的 Web Worker 可以分為兩種不同線程類型,一個是專用線程 Dedicated Worker,一個是共享線程 Shared Worker。兩種類型的線程各有不同的用途。

專用型web worker

專用型worker與創(chuàng)建它的腳本連接在一起,它可以與其他的worker或是瀏覽器組件通信,但是他不能與DOM通信。專用的含義,我想就是這個線程一次只處理一個需求。專用線程在除了IE外的各種主流瀏覽器中都實(shí)現(xiàn)了,可以放心使用。

創(chuàng)建線程

創(chuàng)建worker很簡單,只要把需要在線程中執(zhí)行的JavaScript文件的文件名傳給構(gòu)造函數(shù)就可以了。

線程通信

在主線程與子線程間進(jìn)行通信,使用的是線程對象的postMessage和onmessage方法。不管是誰向誰發(fā)數(shù)據(jù),發(fā)送發(fā)使用的都是postMessage方法,接收方都是使用onmessage方法接收數(shù)據(jù)。postMessage只有一個參數(shù),那就是傳遞的數(shù)據(jù),onmessage也只有一個參數(shù),假設(shè)為event,則通過event.data獲取收到的數(shù)據(jù)。

發(fā)送JSON數(shù)據(jù)

JSON是JS原生支持的東西,不用白不用,復(fù)雜的數(shù)據(jù)就用JSON傳送吧。例如:

代碼如下:

postMessage({'cmd': 'init', 'timestamp': Date.now()});

處理錯誤

當(dāng)線程發(fā)生錯誤的時候,它的onerror事件回調(diào)會被調(diào)用。所以處理錯誤的方式很簡單,就是掛接線程實(shí)例的onerror事件。這個回調(diào)函數(shù)有一個參數(shù)error,這個參數(shù)有3個字段:message - 錯誤消息;filename - 發(fā)生錯誤的腳本文件;lineno - 發(fā)生錯誤的行。

銷毀線程

在線程內(nèi)部,使用close方法線程自己銷毀自己。在線程外部的主線程中,使用線程實(shí)例的terminate方法銷毀線程。

下面從一個例子看線程的基本操作:

HTML代碼:

代碼如下:

<!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代碼:

代碼如下:

//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));

};

把它們放到相同的目錄,運(yùn)行頁面文件,查看控制臺,可以看到運(yùn)行的結(jié)果。

這里還有一點(diǎn),在主線程中,onmessage事件可以使用另外一種方式掛接:

代碼如下:

worker.addEventListener('message', function(event) {

console.log("Result:" + event.data);

}, false);

個人覺得很麻煩,不如用onmessage直接。

使用其他腳本文件

工作線程可以使用全局方法importScripts來加載和使用其他的域內(nèi)腳本文件或者類庫。例如下面都是合法的使用方式:

代碼如下:

importScripts();/* imports nothing */

importScripts('foo.js'); /* imports just "foo.js" */

importScripts('foo.js', 'bar.js');/* imports two scripts */

導(dǎo)入以后,可以直接使用這些文件中的方法??匆粋€網(wǎng)上的小例子:

代碼如下:

/**

* 使用 importScripts 方法引入外部資源腳本,在這里我們使用了數(shù)學(xué)公式計算工具庫 math_utilities.js

* 當(dāng) JavaScript 引擎對這個資源文件加載完畢后,繼續(xù)執(zhí)行下面的代碼。同時,下面的的代碼可以訪問和調(diào)用

* 在資源文件中定義的變量和方法。

**/

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);

}

網(wǎng)上也有網(wǎng)友想到了利用這里的importScripts方法解決資源預(yù)加載的問題(瀏覽器預(yù)先加載資源,而不會對資源進(jìn)行解析和執(zhí)行),道理也很簡單。

線程嵌套

在工作線程中還可以在創(chuàng)建子線程,各種操作還是一樣的。

同步問題

Worker沒有鎖的機(jī)制,多線程的同步問題只能靠代碼來解決(比如定義信號變量)。

共享型SharedWebWorker

共享型web worker主要適用于多連接并發(fā)的問題。因?yàn)橐幚矶噙B接,所以它的API與專用型worker稍微有點(diǎn)區(qū)別。除了這一點(diǎn),共享型web worker和專用型worker一樣,不能訪問DOM,并且對窗體屬性的訪問也受到限制。共享型web worker也不能跨越通信。

頁面腳本可以與共享型web worker通信,然而,與專用型web worker(使用了一個隱式的端口通信)稍微有點(diǎn)不同的是,通信是顯式的通過使用一個端口(port)對象并附加上一個消息事件處理程序來進(jìn)行的。

在收到web worker腳本的首個消息之后,共享型web worker把一個事件處理程序附加到激活的端口上。一般情況下,處理程序會運(yùn)行自己的postMessage()方法來把一個消息返回給調(diào)用代碼,接著端口的start()方法生成一個有效的消息進(jìn)程。

看網(wǎng)上能找到的的唯一個例子:創(chuàng)建一個共享線程用于接收從不同連接發(fā)送過來的指令,然后實(shí)現(xiàn)自己的指令處理邏輯,指令處理完成后將結(jié)果返回到各個不同的連接用戶。

HTML代碼:

代碼如下:

<!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>

腳本文件代碼:

代碼如下:

// 創(chuàng)建一個共享線程用于接收從不同連接發(fā)送過來的指令,指令處理完成后將結(jié)果返回到各個不同的連接用戶。

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;

}

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

這里我們并沒有跟前面的例子一樣使用到了工作線程的 onmessage 事件處理器,而是使用了另外一種方式 addEventListener。實(shí)際上,前面已經(jīng)說過,這兩種的實(shí)現(xiàn)原理基本一致,只是在這里有些稍微的差別,如果使用到了 addEventListener 來接受來自共享線程的消息,那么就要先使用 worker.port.start() 方法來啟動這個端口。之后就可以像工作線程的使用方式一樣正常的接收和發(fā)送消息。

最后陳述

線程中能做的事:

1.能使用setTimeout(), clearTimeout(), setInterval(),clearInterval()等函數(shù)。

2.能使用navigator對象。

3.能使用XMLHttpRequest來發(fā)送請求。

4.可以在線程中使用Web Storage。

5.線程中可以用self獲取本線程的作用域。

線程中不能做的事:

1.線程中是不能使用除navigator外的DOM/BOM對象,例如window,document(想要操作的話只能發(fā)送消息給worker創(chuàng)建者,通過回調(diào)函數(shù)操作)。

2.線程中不能使用主線程中的變量和函數(shù)。

3.線程中不能使用有"掛起"效果的操作命令,例如alert等。

4.線程中不能跨域加載JS。

線程也是需要消耗資源的,而且使用線程也會帶來一定的復(fù)雜性,所以如果沒有充足的理由來使用額外的線程的話,那么就不要用它。

更多信息請查看網(wǎng)頁制作
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機(jī)號
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)