【JavaScript】线程WebWorker

介绍

通过使用WebWorker,我们可以在浏览器后台运行Javascript,而不占用浏览器自身线程。WebWorker可以提高应用的总体性能,并且提升用户体验。如果你想在自己的Web应用中使用WebWorker,不妨来了解一下有关WebWorker的7件事。

1.WebWorker可以让你在后台运行Javascript

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

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

不过WebWorker中的Javascript依然可以使用setTimeout(),setInterval()之类的函数,也可以使用XMLHttpRequest对象来做Ajax通信。

2.有两种WebWorker

Webworkers可分为两种类型:专用线程dedicatedwebworker,以及共享线程sharedwebworker。Dedicatedwebworker随当前页面的关闭而结束;这意味着Dedicatedwebworker只能被创建它的页面访问。与之相对应的Sharedwebworker可以被多个页面访问。在Javascript代码中,“Work”类型代表Dedicatedwebworker,而“SharedWorker”类型代表Sharedwebworker。

在绝大多数情况下,使用Dedicatedwebworker就足够了,因为一般来说在webworker中运行的代码是专为当前页面服务的。而在一些特定情况下,webworker可能运行的是更为普遍性的代码,可以为多个页面服务。在这种情况下,我们会创建一个共享线程的Sharedwebworker,它可以被与之相关联的多个页面访问,只有当所有关联的的页面都关闭的时候,该Sharedwebworker才会结束。相对Dedicatedwebworker,sharedwebworker稍微复杂些。

3.“Worker”对象代表DedicatedWebWorker

现在来看如何使用Dedicatedwebworker。下面的例子中用到了jQuery以及Modernizr作为Javascript库,然后往HTML页面中加入以下代码:

[html]

  1. <!DOCTYPEhtml>
  2. <html>
  3. <head>
  4. <title></title>
  5. <scripttype="text/javascript"src="script/modernizr.js"></script>
  6. <scripttype="text/javascript"src="script/jquery-2.0.0.js"></script>
  7. <scripttype="text/javascript">
  8. $(document).ready(function(){
  9. if(!Modernizr.webworker){
  10. alert("Thisbrowserdoesn‘tsupportWebWorker!");
  11. return;
  12. }
  13. $("#btnStart").click(function(){
  14. varworker=newWorker("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. <inputtype="button"id="btnStart"value="StartProcessing"/>
  26. </form>
  27. </body>
  28. </html>

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

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

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

[javascript]

  1. addEventListener("message",function(evt){
  2. vardate=newDate();
  3. varcurrentDate=null;
  4. do{
  5. currentDate=newDate();
  6. }while(currentDate-date<evt.data);
  7. postMessage(currentDate);
  8. },false);

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

所以当点击“StartProcessing”按钮,页面会在10秒钟后把当时的时刻alert出来。在这10秒钟内页面依然可以响应鼠标键盘事件。

4.“SharedWorker”对象代表SharedWebWorker

前面的代码使用的是dedicatedwebworker。这一节会用sharedwebworker代替dedicatedwebworker,来区别两者的不同。下面是同一个例子的sharedwebworker版本:

[javascript]

  1. addEventListener("message",function(evt){
  2. vardate=newDate();
  3. varcurrentDate=null;
  4. do{
  5. currentDate=newDate();
  6. }while(currentDate-date<evt.data);
  7. postMessage(currentDate);
  8. },false);

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

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

[javascript]

  1. varport;
  2. addEventListener("connect",function(evt){
  3. port=evt.ports[0];
  4. port.addEventListener("message",function(evt){
  5. vardate=newDate();
  6. varcurrentDate=null;
  7. do{
  8. currentDate=newDate();
  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.WebWorker使用XMLHttpRequest与服务端通信

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

[javascript]

  1. addEventListener("message",function(evt){
  2. varxhr=newXMLHttpRequest();
  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]

  1. namespaceWebWorkerDemo
  2. {
  3. publicclassLengthyTaskHandler:IHttpHandler
  4. {
  5. publicvoidProcessRequest(HttpContextcontext)
  6. {
  7. System.Threading.Thread.Sleep(10000);
  8. context.Response.ContentType="text/plain";
  9. content.Response.Write("Processingsuccessful!");
  10. }
  11. publicboolIsReusable
  12. {
  13. get
  14. {
  15. returnfalse;
  16. }
  17. }
  18. }
  19. }

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

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

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

[javascript]

  1. $("#btnStart").click(function(){
  2. varworker=newWorker("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()方法终止WebWorker

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

总结

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

【JavaScript】线程WebWorker,布布扣,bubuko.com

时间: 2024-11-10 07:34:40

【JavaScript】线程WebWorker的相关文章

再看JavaScript线程

继上篇讨论了一些关于JavaScript线程的知识,我们不妨回过头再看看,是不是JavaScript就不能多线程呢?看下面一段很简单的代码(演示用,没考虑兼容问题): 代码判断一: <div id="div"> click me </div> <script> var div=document.getElementById("div"); div.addEventListener('click',function(){ alert

javascript线程解释(setTimeout,setInterval你不知道的事)

原文:http://www.iamued.com/qianduan/1645.html 今天看到这篇文章,学到了不少东西 特此发出来 和大家分享 JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不少人都深有同感, 例如 setTimeout( function(){ alert('你好!'); } , 0); setInterval( callbackFunction , 100); 认为se

JavaScript线程机制

浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:JS引擎线程(用于处理JS).GUI渲染线程(用于页面渲染).浏览器事件触发线程(用于控制交互). 除此之外,有一些执行完就终止的线程,如Http请求线程. 1.        javascript引擎线程是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序. 2.        GUI渲染线程负责渲染浏览器界面,当界面需要重

Javascript线程及定时机制

setTimeout.setInterval的使用 Javascript api文档中定义setTimeout和setInterval第二个参数意义分别为间隔多少毫秒后回调函数被执行和每隔多少毫秒回调函数被执行.但随着工作经验的积累,我们发现事实并非如此. 比如 div.onclick=function(){ setTimeout(function(){ document.getElementById('input').focus(); },0); } 就解释不通了,立即执行就立即执行呗,干嘛还

JavaScript线程机制与事件机制

一.进程与线程 1.进程 进程是指程序的一次执行,它占有一片独有的内存空间,可以通过windows任务管理器查看进程(如下图).同一个时间里,同一个计算机系统中允许两个或两个以上的进程处于并行状态,这是多进程.比如电脑同时运行微信,QQ,以及各种浏览器等.浏览器运行是有些是单进程,如firefox和老版IE,有些是多进程,如chrome和新版IE. 2.线程 有些进程还不止同时干一件事,比如Word,它可以同时进行打字.拼写检查.打印等事情.在一个进程内部,要同时干多件事,就需要同时运行多个"子

JavaScript线程(第八天)

js是单线程的: js中的线程分为三种 1.页面渲染 2.主代码逻辑 3.事件触发: 下面我们来看一段代码 <script> setTimeout(function(){    console.log(123);    },0);    </script> 按照js的api来看,上面的代码应该是0秒后执行,但真的是这样吗? js中没有控制线程的,所以无法让线程进行睡眠:但我们可以用alert阻塞线程: 当我们在后面加alert后,我们看到,123并没有立刻输出:而是等待弹窗关闭后才

第十一章:WEB浏览器中的javascript

客户端javascript涵盖在本系列的第二部分第10章,主要讲解javascript是如何在web浏览器中实现的,这些章节介绍了大量的脚本宿主对象,这些对象可以表示浏览器窗口.文档树的内容.这些章节同样涵盖重要的web应用所需要的网络编程API.本地存储和检索数据.画图等.主要包含内容有以下章节: web浏览器中的javascript / window对象 /  脚本化文档 /  脚本化css / 事件处理 / 校本化http / jQuery类库 / 客户端存储  /  多媒体和图形编程 /

关于javascript的单线程和异步的一些问题

关于js单线程和异步方面突然就糊涂了,看别人的文章越看越糊涂,感觉这方面是个坑,跳进去就不好跳出来.再去看,看着看着感觉自己明白了一些东西,也不知道对不对,反正是暂时把自己说服了,这样理解能理解的通,就总结了一下几个问题. 问题1:浏览器的线程与进程 看了很多资料,很多人对进程和线程是不加区分的,甚至上面说的说进程下面就改口为线程了.按我的理解进程是比线程大的一个概念,当一个程序运行就开辟单个或多个进程地址空间(IE.Firefox.Safari均是单进程模式,Chrome则上多进程大),然后各

JavaScript中定时器

JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务. setTimeout() setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行.它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器. var timerId = setTimeout(func|code, delay) 上面代码中,setTimeout函数接受两个参数,第一个参数func|cod