您的位置:首页 > Web前端 > HTML5

HTML5之Web Worker

2013-11-18 16:06 218 查看
Web Worker是什么:

web worker是html5提供的一个多线程解决方案,(以下我们简称为wWorker),大家都知道js是单线程执行的,所谓多线程解决方案也就是不需要js在执行时候摁着一个线程可劲使用,

比如有些时候我们不小心会弄出死循环 或者大量计算时候,浏览器就会在它执行的线程中去执行我们的计算,从而导致ui渲染线程挂起浏览器就over了,

这就是单线程处理的结果,多线程就是解决了这么一个问题。在之前我们利用js来模拟多线程一般都是用setTimeOut延迟处理时间来达到”多线程“处理效果。但是这种处理都是手动规定其闲余时间去处理内部的函数,

我们并不知道到底处理了多久 或者应该处理多久,只能去猜测。假如服务端每隔两秒向里面更新一下数据,而setTimeOut执行事件为3秒,这样就会有数据处理丢失问题了。并且用setTimeout模拟起来计算时间模拟比较复杂。

wWorker在浏览器中开辟一个新线程,将需要大量计算的或者容易导致阻塞的程序放置于另一个线程中,

而其他执行的东东还是依然在本线程中工作。这样一来大大提高了浏览器运行效率。html5规范了wWorker三大特性:

1.能够长时间运行(响应);

2.理想的启动性能以及理想的内存消耗;

3.wWorkers 允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的及时响应。

wWorker虽然不能直接处理dom元素(毕竟不是实际js脚本)但是可以创建数据消息来通过主线程的回调函数去执行dom。

Web Worker如何使用

举个例子:

html页面

<!DOCTYPE HTML>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<script type="text/javascript">

//WEB页主线程

var worker =new Worker("worker.js"); //创建一个线程对象并向它传递将在新线程中执行的脚本的URL

worker.postMessage("hello wWorker!"); //向新线程发送数据

worker.onmessage =function(evt){ //接收worker传过来的数据函数

console.log(evt.data); //执行worker发送来的数据

}

</script>

</head>

<body></body>

</html>

worker.js(新开辟线程)

onmessage=function(event){

postMessage(event.data);//发送给主线程接受到数据(‘hello wWorker!’)

}

在web环境下执行html代码后会在控制台输出hello wWorker!

分析一下整个应用执行过程:

1.在主线程实例化一个worker并且加载一个js的url地址作为参数

2.通过worker.postMessage向新线程发送一个参数或者数据

3.新线程绑定onmessage处理主线程发送过来的数据

4.新线程处理完主线程发来数据后利用postMessage方法向主线程发送数据

5.主线程绑定onmessage处理新线程返回的数据

Web Worker能做什么

我们知道应用该方法可以通过开辟一个新线程来协助处理一个主线程的复杂工作,举个例子(来自互联网)

fibonacci数列在数学上以递归方法定义F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*),而javascript的常用实现为:

var fibonacci =function(n) {

return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);

};

因为js执行计算是单线程的,在计算如此大数据量时候 浏览器往往就会被挂起,从而导致页面假死状态。实则是浏览器线程在后台进行计算,在这个计算过程中页面是不会继续向下进行渲染等操作的,

所以我们可以通过worker将计算放入一个新的线程中去,从而避免单线程工作阻塞浏览器继续执行。

主线程页面

<!DOCTYPE HTML>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<title>web worker fibonacci</title>

<script type="text/javascript">

window.onload =function(){

var timer = (new Date()).valueOf();

var worker =new Worker('worker.js');

worker.postMessage(40);

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

var timer2 = (new Date()).valueOf();

console.log( '结果:'+event.data+'用时:'+ ( timer2-timer));

}, false);

}

</script>

</head>

<body>

</body>

</html>

新线程worker.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));

};

在控制台我们可以看到

结果:102334155用时:9452 ;

本机测试非worker与worker运行时间都是差不多的(跟网上所说的非worker差距十几秒)。但还是不能否认它的优点的:

好处就是它不会阻塞线程,如果我们在onload最后加一句alert(11),比较一下worker以及非worker如下:

非worker:页面加载时候浏览器一直在计算,等到计算完毕,控制台打印出结果后才会弹出11.

worker:onload会立即弹出11,确定后等待几秒钟控制台才会打印出结果。

通过这个分析我们可以知道,非worker在计算过程中js是不会继续向下执行的,而通过worker我们可以使得js异步执行代码计算。

不要误以为点击alert之后worker才会工作,实际是alert阻塞了主线程的进程使得js代码无法进行运行而已。平常我们可以用console来替代alert进行调试的。

web worker总结:

优点:

1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信

局限性:

1.不能跨域加载JS

2.worker内代码不能访问DOM

3.各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行

综上所述:web worker目前所能做的(应该说是最适合的)也就是新开辟一个线程去计算大数据或者处理并发事件,而不影响主线程进程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: