在 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+"<br/>"; 
         }; 
     } 
 </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());

演示地址:http://lovermap.sinaapp.com/test/test.html

 

由于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.不是每个浏览器都支持这个新特性

 

posted on 2015-04-19 11:26  floralam  阅读(1201)  评论(1编辑  收藏  举报