关于Web Worker你必须知道的7件事

介绍

经过使用Web Worker, 咱们能够在浏览器后台运行Javascript, 而不占用浏览器自身线程。Web Worker能够提升应用的整体性能,而且提高用户体验。若是你想在本身的Web应用中使用Web Worker, 不妨来了解一下有关Web Worker的7件事。javascript

1. Web Worker 可让你在后台运行Javascript

通常来讲Javascript和页面的UI会共用一个线程,因此当点击一个按钮开始运行Javascript后,在这段代码运行完毕以前,页面是没法响应用户操做的,换句话来讲就是被“冻结”了。而这段代码能够交给Web Worker在后台运行,那么页面在Javascript运行期间依然能够响应用户操做。后台会启动一个worker线程来执行这段代码,用户能够建立多个worker线程。因此你能够在前台作一些小规模分布式计算之类的工做,不过Web Worker有如下一些使用限制:html

 

  • Web Worker没法访问DOM节点;
  • Web Worker没法访问全局变量或是全局函数;
  • Web Worker没法调用alert()或者confirm之类的函数;
  • Web Worker没法访问window、document之类的浏览器全局变量;

 

不过Web Worker中的Javascript依然可使用setTimeout(),setInterval()之类的函数,也可使用XMLHttpRequest对象来作Ajax通讯。java

2. 有两种Web Worker

Web workers可分为两种类型:专用线程dedicated web worker,以及共享线程shared web worker。 Dedicated web worker随当前页面的关闭而结束;这意味着Dedicated web worker只能被建立它的页面访问。与之相对应的Shared web worker能够被多个页面访问。在Javascript代码中,“Work”类型表明Dedicated web worker,而“SharedWorker”类型表明Shared web worker。jquery

在绝大多数状况下,使用Dedicated web worker就足够了,由于通常来讲在web worker中运行的代码是专为当前页面服务的。而在一些特定状况下,web worker可能运行的是更为广泛性的代码,能够为多个页面服务。在这种状况下,咱们会建立一个共享线程的Shared web worker,它能够被与之相关联的多个页面访问,只有当全部关联的的页面都关闭的时候,该Shared web worker才会结束。相对Dedicated web worker,shared web worker稍微复杂些。web

3. “Worker”对象表明Dedicated Web Worker

如今来看如何使用Dedicated web worker。下面的例子中用到了jQuery以及Modernizr做为Javascript库,而后往HTML页面中加入如下代码:数据库

 

[html]  view plain copy
 
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <title></title>  
  5. <script type="text/javascript" src="script/modernizr.js"></script>  
  6. <script type="text/javascript" src="script/jquery-2.0.0.js"></script>  
  7. <script type="text/javascript">  
  8. $(document).ready(function(){  
  9. if(!Modernizr.webworker){  
  10. alert("This browser doesn't support Web Worker!");  
  11. return;  
  12. }  
  13. $("#btnStart").click(function(){  
  14. var worker = new Worker("script/lengthytask.js");  
  15. worker.addEventListener("message", function(evt){  
  16. alert(evt.data);  
  17. }, false);  
  18. worker.postMessage(10000)  
  19. });  
  20. });  
  21. </script>  
  22. </head>  
  23. <body>  
  24. <form>  
  25. <input type="button" id="btnStart" value="Start Processing"/>  
  26. </form>  
  27. </body>  
  28. </html>  

 

这个HTML页面中有个按钮,点击后会运行一个Javascript文件。上面的代码中首先检测当前浏览器是否支持Web Worker,不支持的话,就跳出提醒信息。浏览器

按钮的点击事件中建立了Worker对象,并给它指定了Javascript脚本文件——lengthytask.js(稍后会有代码),而且给Worker对象绑定了一个“message”事件。该事件会在后台代码(lengthytask.js)向页面返回数据时触发。“message”事件能够经过event.data来获取后台代码传回的数据。最后,postMessage方法正式执行lengthytask.js,该方法还能够向后台代码传递参数, 后台代码一样经过message事件获取该参数。服务器

下面是lengthytask.js主要包含的代码:asp.net

 

[javascript]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. addEventListener("message", function(evt){  
  2. var date = new Date();  
  3. var currentDate = null;  
  4. do {  
  5. currentDate = new Date();  
  6. }while(currentDate - date < evt.data);  
  7. postMessage(currentDate);  
  8. }, false);  


以上代码在后台监听message时间,并获取页面传来的参数:10000;这里其实是一个计时函数:在message事件被触发10000毫秒以后,把结果(currentDate)传给页面。分布式

 

因此当点击“Start Processing”按钮,页面会在10秒钟后把当时的时刻alert出来。在这10秒钟内页面依然能够响应鼠标键盘事件。

4. “SharedWorker”对象表明Shared Web Worker

前面的代码使用的是dedicated web worker。 这一节会用shared web worker代替dedicated web worker,来区别二者的不一样。下面是同一个例子的shared web worker版本:

 

[javascript]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. addEventListener("message", function(evt){  
  2. var date = new Date();  
  3. var currentDate = null;  
  4. do {  
  5. currentDate = new Date();  
  6. }while(currentDate - date < evt.data);  
  7. postMessage(currentDate);  
  8. }, false);  

请注意加黑的代码,这里建立了一个SharedWorker对象,并把message事件绑定在shared worker的port对象上;一样由port对象发起postMessage, 开始执行后台代码sharedlengthytask.js。

下面是sharedlengthytask.js的主要代码:

 

[javascript]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. var port;  
  2. addEventListener("connect", function(evt){  
  3. port = evt.ports[0];  
  4. port.addEventListener("message", function(evt){  
  5. var date = new Date();  
  6. var currentDate = null;  
  7. do {  
  8. currentDate = new Date();  
  9. }while(currentDate - date < evt.data);  
  10. port.postMessage(currentDate);  
  11. }, false);  
  12. port.start();  
  13. }, false);  


使用SharedWorker对象的后台代码须要绑定connect和message事件, connect事件会在页面上的port被start时触发。以后的message事件的回调函数与以前的基本相同,最后port调用postMessage方法把结果传回给页面。

 

5. Web Worker使用XMLHttpRequest与服务端通讯

有些状况下,web worker还须要与服务器进行交互。好比页面可能须要处理来自数据库中的信息,咱们就须要使用Ajax技术与服务器交互,下面代码包含了web worker如何从服务端获取数据:

 

[javascript]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. addEventListener("message", function(evt){  
  2. var xhr = new XMLHttpRequest();  
  3. xhr.open("GET", "lengthytaskhandler.ashx");  
  4. xhr.onload = function(){  
  5. postMessage(xhr.responseText);  
  6. };  
  7. xhr.send();  
  8. },false);  


上面的代码向服务端的asp.net服务lengthytaskhandler.ashx发出GET请求。并注册了获取数据后的onload事件。下面的代码是服务端的lengthytaskhandler.ashx:

 

 

[csharp]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. namespace WebWorkerDemo  
  2. {  
  3. public class LengthyTaskHandler:IHttpHandler  
  4. {  
  5. public void ProcessRequest(HttpContext context)  
  6. {  
  7. System.Threading.Thread.Sleep(10000);  
  8. context.Response.ContentType = "text/plain";  
  9. content.Response.Write("Processing successful!");  
  10. }  
  11. public bool IsReusable  
  12. {  
  13. get  
  14. {  
  15. return false;  
  16. }  
  17. }  
  18. }  
  19. }  


如你所见,ProcessRequest模拟了一个长时间运行的任务,并返回了“Processing successful!”的消息。

 

6. 经过Error事件捕捉错误信息

当咱们把愈来愈复杂的逻辑加到Web Worker里时,错误处理机制是必不可少的。而Web Worker偏偏提供了error事件,供开发者捕捉错误信息。下面的代码展现了如何绑定error事件:

 

[javascript]  view plain copy 在CODE上查看代码片 派生到个人代码片
 
  1. $("#btnStart").click(function(){  
  2. var worker = new Worker("scripts/lengthytask.js");  
  3. worker.addEventListener("error", function(evt){  
  4. alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename);  
  5. }, false);  
  6. worker.postMessage(10000);  
  7. });  


如上可见, Worker对象能够绑定error事件;并且evt对象中包含错误所在的代码文件(evt.filename)、错误所在的代码行数(evt.lineno)、以及错误信息(evt.message)。

 

7. 经过terminate()方法终止Web Worker

有些状况下,咱们可能须要强制终止执行中的Web Worker。Worker对象提供了terminate()来终止自身执行任务,被终止的Worker对象不能被重启或重用,咱们只能新建另外一个Worker实例来执行新的任务。

总结

Web Worker能够在后台执行脚本,而不会阻塞页面交互。Worker对象分为两种:专用式Web Worker和共享式Web Worker:专用式的Web Worker只能被当个页面使用,而共享式的Web Worker能够在被多个页面使用。另外,本文还介绍了Web Worker的错误处理机制,以及使用Ajax与服务端交互。