在HTML5中提出了工作线程(Web Workers)的概念,即多线程概念,可以将一些大量计算的代码交给web worker运行而不冻结用户界面。
Web Workers 的三大主要特征:
1)能够长时间运行(响应)
2)理想的启动性能
3)理想的内存消耗
Web Workers允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的及时响应。
Web Workers为
Web前端网页上的脚本提供了一种能在后台进程中运行的方法。一旦它被创建,Web Workers就可以通过
postMessage向任务池发送任务请求,执行完之后再通过postMessage返回消息给创建者指定的事件处理程序( 通过 onmessage
进行捕获 )。Web
Workers进程能够在不影响用户界面的情况下处理任务,并且,它还可以使用XMLHttpRequest来处理I/O,但通常,后台进程(包括
Web Workers 进程)不能对DOM进行操作。如果希望后台程序处理的结果能够改变DOM,只能通过返回消息给创建者的回调函数进行处理。
需要在客户端页面的JavaScript代码中new
一个Worker实例出来,参数是需要在另一个线程中运行的JavaScript文件名称。然后在这个实例上监听onmessage事件。最后另一个线程中的JavaScript就可以通过调用postMessage方法在这两个线程间传递数据了。
**主程序中,创建worker实例,监听onmessage事件 **
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Web worker</title>
<script type="text/JavaScript">
function init(){
var worker = new Worker('compute.js');
//event 参数中有data属性,就是子线程中返回的结果数据
worker.onmessage= function (event) {
// 把子线程返回的结果添加到 div 上
document.getElementById("result").innerHTML +=
event.data+"
";
};
}
</script>
</head>
<body onload="init()">
<div id="result"></div>
</body>
</html>
在客户端的compute.js开辟了一个新的线程,不起阻塞执行的效果,并且提供主线程和新线程之间的数据交互接口。只是简单的重复多次加和操作,最后通过postMessage方法把结果返回给主线程,目的就是等待一段时间。而在这段时间内,主线程不应该被阻塞,用户可以通过拖拽浏览器,变大缩小浏览器窗口等操作测试这一现象。这个非阻塞主线程的结果就是Web
Workers想达到的目的。
**
compute.js 中调用 postMessage 方法返回计算结果**
var i=0;
function timedCount(){
for(var j=0,sum=0;j<100;j++){
for(var i=0;i<1000000;i++){
sum+=i;
}
}
// 调用 postMessage 向主线程发送消息
postMessage(sum);
}
postMessage("获取计算之前的时间,"+new Date());
timedCount();
postMessage("获取计算之后的时间,"+new Date());
由于javascript是单线程执行的,在复杂地运算的过程中浏览器不能执行其它javascript脚本,UI渲染线程也会被挂起,从而导致浏览器进入僵死状态。使用web worker将数列的计算过程放入一个新线程里去执行将避免这种情况的出现。
除了可以使用web
worker加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信外;可以在worker中通过importScripts(url)加载另外的脚本文件,使用
setTimeout(), clearTimeout(), setInterval(), and
clearInterval(),使用XMLHttpRequest来发送请求,访问navigator的部分属性。
但是也是存在一定的局限性:
1.不能跨域加载JS(同源策略限制)
2.worker内代码不能访问DOM
3.各个浏览器对Worker的实现不大一致
4.不是每个浏览器都支持这个新特性