Javascript执行机制
在HTML5之前,浏览器中JavaScript的运行都是以单线程的方式工作的,虽然有多种方式实现了对多线程的模拟(例如:Javascript中的setinterval方法,setTimeout方法等),但是在本质上程序的运行仍然是由JavaScript的引擎以单线程调度的方式进行的。在HTML5中引入的工作线程使得浏览器端的Java脚本引擎可以并发地执行的Javascript代码,从而实现了对浏览器端多线程编程的良好支持。
使用Javascript中的多线程-网页工人
。HTML5中的Web工作可以分为两种不同线程类型,一个是专用线程专用的辅助,一个是共享线程共享工人两种类型的线程各有不同的用途。
专用型网络工作者
专用型工作者与创建它的脚本连接在一起,它可以与其他的工作者或浏览器组件通信,但是他不能与DOM通信。专用的含义,我想就是这个线程一次只处理一个需求。专用线程在除IE外的各种主流浏览器中都实现了,可以放心使用。
创建线程
创建工人很简单,只要把需要在线程中执行的JavaScript文件的文件名传给构造函数就可以可以了。
线程通信
在主线程与子线程间进行通信,使用的是线程对象的postMessage和onmessage方法。一个参数,那就是传递的数据,onmessage也只有一个参数,假设为事件,则通过event.data获取收到的数据。
发送JSON数据
JSON是JS原生支持的东西,不用白不用,复杂的数据就用JSON传送吧。例如:
复制代码代码如下:
postMessage({'cmd':'init','timestamp':Date.now()});
因此处理错误
的方式很简单,就是挂接线程实例的onerror事件。这个变量函数有一个参数错误,这个参数有3个变量:消息-错误消息;文件名-发生错误的脚本文件; LINENO -发生错误的行
销毁线程
。在线程内部,使用靠近方法线程自己销毁自己在线程外部的主线程中,使用线程实例的终止方法销毁线程。
下面从一个例子看线程的基本操作
:
复制代码代码如下:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv =“ Content-Type” content =“ text / html; charset = utf-8” />
<title>网络工作者斐波那契</ title>
<脚本类型=“ text / javascript”>
onload = function(){
var worker = new Worker('fibonacci.js');
worker.onmessage = function(event){
console.log(“ Result:” + event.data);
};
worker.onerror =函数(错误){
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));
};
将它们放到相同的目录,运行页面文件,查看控制台,可以看到运行的结果。
这里还有一点,在主线程中,onmessage事件可以使用另一种方式挂接:
复制代码代码如下:
worker.addEventListener('message',function(event){
console.log(“ Result:” + event.data);
},false);
个人觉得很麻烦,不如用onmessage直接。
使用其他脚本文件
工作线程可以使用数组方法importScripts来加载和使用其他域内脚本文件或类库。例如以下都是合法的使用方式:
复制代码代码如下:
importScripts(); / *不导入任何内容* /
importScripts('foo.js'); / *仅导入“ foo.js” * /
importScripts('foo.js','bar.js'); / *导入两个脚本* /
引入以后,可以直接使用这些文件中的方法。看一个网上的小例子:
复制代码代码如下:
/ **
*使用importScripts方法约会外部资源脚本,在这里我们使用了数学公式计算工具库math_utilities.js
*当JavaScript引擎对这个资源文件加载完毕后,继续执行以下的代码。同时,下面的代码可以访问和调用
*在资源文件中定义的变量和方法。
** /
importScripts( 'math_utilities.js');
onmessage =函数(事件)
{
var first = event.data.first;
var second = event.data.second;
计算(第一,第二);
};
函数calculate(first,second){
//做计算工作
var common_divisor = divisor(first,second);
var common_multiple = multiple(first,second);
postMessage(“工作完成!” +
“最小公倍数是” + common_divisor +
“,最大公数是” + common_multiple);
}
网上也有网友想到了利用这里的importScripts方法解决资源预加载的问题(浏览器预先加载资源,而不会对资源进行解析和执行),道理也很简单。
线程嵌套
在工作线程中还可以在创建³³子线程,各种操作还是一样的。
同步问题
,工人没有锁的机制,多线程的同步问题只能靠代码来解决(比如定义信号变量)。
共享型SharedWebWorker
共享型网络工作者主要适用于多连接并发的问题。因为要处理多连接,所以它的API与专用型worker稍微有点区别。除了这一点,共享型web worker和专用型worker一样,不能访问DOM,并且对某些属性的访问也受到限制。共享类型的web worker也不能跨越通信。
页面脚本可以与共享类型的web worker通信,然而,与专用类型的web worker(使用了一个隐式的端口通信)稍微有点不同的是,通信是显式的通过使用一个端口(端口)对象并附加上一个消息事件处理程序来进行的。
在收到的web worker脚本的首个消息之后,共享类型的web worker将一个事件处理程序附加到激活的端口上。一般情况下,处理程序会运行自己的的postMessage()方法来把一个消息返回给调用代码,接着端口的开始()方法生成一个有效的消息进程。
看网上能找到的的唯一个例子:创建一个共享线程用于接收从不同连接发送过来的指令,然后实现自己的指令处理逻辑,指令处理完成后将结果返回到各个不同的连接用户。
HTML代码:
复制代码代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset =“ UTF-8”>
<title>共享工作程序示例:如何在HTML5中使用共享工作程序</ title>
<script>
var worker = new SharedWorker('sharedworker .js');
var log = document.getElementById('response_from_worker');
worker.port.addEventListener('message',function(e){
//将响应数据记录在网页中
log.textContent = e.data;
},false);
worker.port.start();
worker.port.postMessage('从用户网页ping ..');
var Instructions = {instruction:input.value};
worker.port.postMessage(指令);
}
</ script>
</ head>
<body onload =''>
<output id ='response_from_worker'>
共享工作程序示例:如何在HTML5中使用共享工作程序
</ output>
向共享工作程序发送指令:
<input type =“ text“ autofocus oninput =” postMessageToSharedWorker(this); return false;“>
</ input>
</ body>
</ html>
脚本文件代码:
复制代码代码如下:
//创建一个共享线程用于接收从不同的连接发送过来的指令,指令处理完成后将结果返回到各个不同的连接用户。var
connect_number = 0;
onconnect = function(e){
connect_number = connect_number + 1;
//在此处获得第一个端口
var port = e.ports [0];
port.postMessage('一个新连接!当前连接号为'
+ connect_number);
port.onmessage = function(e){
//从请求者那里获取指令varstruction
= e.data.instruction;
var results = execute_instruction(instruction);
port.postMessage('Request:'+ instruction +'响应'+ results
+'from shared worker ...');
};
};
/ *
*此功能将用于执行从请求者发送的指令
* @param指令
* @return
* /
函数execute_instruction(instruction)
{
var result_value;
//在这里
执行逻辑//执行指令...
return result_value;
}
在上面的共享线程示例中,在主页面即各个用户连接页面构造出一个共享线程对象,然后定义了一个方法postMessageToSharedWorker向共享线程发送来之用户的指令。同时,在共享线程的实现代码片段中定义之后,用onconnect事件处理器接受来自不同用户的连接,解析其传递过来的指令。最后,定义一个方法execute_instruction使用执行用户的指令,指令执行完成后将结果返回给给每个用户。
这里我们并没有跟前面的例子一样使用到了工作线程的onmessage事件处理器,而是使用另一种方式addEventListener。实际上,前面已经说过,这两种的实现原理基本一致,只是在这里有些稍微的区别,如果使用到了addEventListener来接受来自共享线程的消息,那么就要先使用worker.port.start()方法来启动这个端口。之后就可以像工作线程的使用方式一样正常的接收和发送消息。
求最后,书写马虎。
线程中能做的事:
1.能使用的setTimeout(),clearTimeout(),setInterval的(),clearInterval()等函数
。2.能使用导航对象
3.能。使用的XMLHttpRequest来发送请求
。4.可以在线程中使用Web存储
。5.线程中可以用自本。电子杂志的线程作用域
线程中不能做的事:
1.线程中是不能使用除导航器外的DOM / BOM对象,例如窗口,文档(想要操作的话只能发送消息给worker创建者,通过可变函数操作)
。2.线程中不能使用主线程中的变量和函数。
3.线程中不能使用有“挂起”效果的操作命令,例如警报等。
4.线程中不能跨域加载JS。
线程也是需要消耗资源的,而且使用线程也会带来一定的复杂性,所以如果没有充足的理由来使用额外的线程的话,那么就不要用它。
如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h61427.shtml