前几天看了一道阿里的笔试题,说的是在JavaScript中如何实现多线程。众所周知,在JavaScript中,所有代码都是单线程的。当然,有人会说,用setTimeout或setInterval不就可以了吗。其实这只是一个假象,我们在setTimeout或setInterval中设定的时间间隔只是告诉浏览器,隔这么多秒后把这个函数放到执行队列中,至于这个函数什么时候执行,你完全无法预知。不信的可以自己在调用setTimeout或setInterval之前先执行一个死循环。

  也就是说,我们用setTimeout或setInterval只能模拟多线程执行,但实际上也还是单线程。当然,我这里讲的Web Workers也并不是JavaScript的多线程,而是一种更高效的编程技术,简单地说,它就是运行在JavaScript后台的线程,由于它是异步的,所以,你也可以把它看成是多线程。

  好了,讲了这么多废话,让我们进入正题吧。Web Workers又分为专用Worker和共享Worker。虽然Safari5、Chrome和Opera10.6都实现了Worker,但由于该规范尚未完稿,因此很可能还会变动。我们这里只介绍专用Worker。

  首先,我们要准备2份js文件,一份用于页面中,例如demo.js,一份则是用于Web Workers中,例如workers.js,我们把demo.js包含于html标记<script>中即可。位于demo.js中的代码如下:

1 var data=[23,4,7,9,2,14,6,651,87,41,7798,24];
2 var worker=new Worker("workers.js");//创建Web Workers
3 worker.onmessage=function(event){//回调函数
4     var data=event.data;
5     alert(data);
6 };
7 worker.postMessage(data);//传输数据

  这里代码的含义是把data的数据通过异步方式发送给works.js中处理,有消息返回的时候把它alert出来,如上所示,数据保留在event.data中。workers.js中的代码如下:

1 self.onmessage=function(event){
2     var data=event.data;
3     data.sort(function(a,b){
4         return a-b;
5     });
6     self.postMessage(data);
7 };

  函数的功能是把接收到的数据排序然后返回,这里有几点需要说明一下:

  1.Web Worker中的全局对象是worker本身,也就是说,在这里,this和self都是指worker对象;

  2.在这个环境中,拥有navigator对象,包含onLine、appName、appVersion、userAgent和platform属性;

  3.只读的location对象;

  4.setTimeout()、setInterval()、clearTimeout()和clearInterval()方法;

  5.XMLHttpRequest构造函数。

  显然,Web Worker的运行环境与页面环境相比,功能是相当有限的。

  当页面在worker对象上调用postMessage()时,数据会以异步的方式被传递给worker,进而触发worker中的message事件。为了处理来自页面的数据,同样也需要创建一个onmessage事件处理程序。