前几天看了一道阿里的笔试题,说的是在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事件处理程序。