2010-8-7 update:很悲剧的发现,Web Worker不支持跨域调用js文件。同时,经过测试,发现在Worker进程中的onmessage函数不能使用function onmessage(){}这种方式来声明,否则chrome、safari、opera不能执行它,切记~(实现Worker,FF比chrome、opera、safari兼容性好多了)
如果你使用window.onmessage=function(){}来声明onmessage方法,FF、Chrome等都提示window未定义的错误,这就很奇怪撂。难道Worker进程中不存在window这个对象?
—————————– 更新分界线 ——————————
javascript单线程任务式的运行代码,这是大家普遍都知道的事情,有时候为了模拟多线程,会使用setTimeout/setInterval的方式,但是这个并不能解决实质的问题。Web Worker — javascript的“多核”时代来了!
Worker也已经出现的比较早了,记得当初首先是在Mozilla网站看到关于它的语法和特点介绍,今天在逛Opera看到了关于它的说明文档:Web Workers rise up!。觉得来详细的分析下它的原理是很有必要的了。下面是我对它的一点点看法:
Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类来独辟一个新的线程,来处理外联的一个javascript文件,起到互不阻塞执行的效果,并且提供主线程和新线程之间数据交换的接口:postMessage,onmessage。而它的数据交换方式有点类似于Ajax的异步请求,都是浏览器“暗地里”传输的。下面是我分析之后得出的一个流程图:

从上面的流程图的数据交换方式是这样的(结合下面的DEMO来查看):主线程通过实例化Worker类,来开辟一个新的进程,这个进程就会执行实例化Worker时指定的js文件,如果需要交换数据,则主线程通过Worker对象的postMessage方法来发送数据给新进程的js文件,新进程的js通过onmessage函数来接收主线程发送来的数据,经过处理之后,又使用postMessage方法发送回去,最后主线程通过Worker类的onmessage方法来接收新线程的js发送经过处理后的数据,over,这样就结束了两个线程之间的数据交互。
[javascript]
//worker.js
onmessage = function (evt){
var d = evt.data;//通过evt.data获得发送来的数据
postMessage(d+"双核时代来啦");//再发送回去,礼尚往来
}
[/javascript]
[javascript]
//main thread
var w = new Worker("worker.js");
w.postMessage("javascript");
w.onmessage = function(evt){
alert(evt.data);//获取新线程的js发送来的数据
}
[/javascript]
原理看起来很简单,但是在接触它的时候,有几个疑问在脑子里转:
- Worker类接收js文件的url为参数,是否可以接收js代码字符串呢?
- 如果外联的js文件处理的时间很长,这样主线程的Worker对象的onmessage和postMessage执行会不会报错?
- 会不会存在编码问题?
经过测试之后,答案一一揭晓:Worker类不能够接收js代码字符串,比如:”new Worker(‘onmessage=function…’)”;onmessage在这里是一种类似于click等的事件,它会在接收到数据之后触发,所以不用顾虑外联js文件处理的时间问题;因为Worker类的参数是一个url,它就会向服务器请求这个文件,发送一个HTTP请求,这里就又回归到Ajax的模式了,不过要注意编码问题。
还有一点需要注意的是:在外联js文件中,onmessage方法的声明方式千万别带上var,否则在Chrome,Safari,Opera下会失效,FF在有没有var都可以。
您好~我是王培栋 最近一直在学习中~~我的QQ:654371743
这篇不错 西红柿总是先研究新东东.给大家分享..顶
第一次拜访,真的不错
谢谢分享!!
引用: 在IE中模拟Worker | 西红柿青炒番茄
如果你使用window.onmessage=function(){}来声明onmessage方法,FF、Chrome等都提示window未定义的错误,这就很奇怪撂。难道Worker进程中不存在window这个对象?
—-
在worker.js里的onmessage=实际上名字空间不是window
请在worker里postMessage( this.toString() ),就知道
打印为object DedicatedWorkerContext]。
http://www.w3.org/TR/workers/#the-global-scope
worker进程的确不存在window对象。
原来如此,哈哈……
当时我也觉得奇怪,测试之后发现这个问题
importScripts(“lee.js”,”test.js”,”ajax.js”,”wce_Communicator.js”,”wce.js”);
self.onmessage=function(message){
var a=”555555″;
var s= Test(a);
self.postMessage(“hello,”+message.data+s+”!”);
var command =new WCECommand(“http://10.90.3.43:8080/CXServer/cx/1.0/registration”,”aaa”,”Get”,”bbb”);
sendAjaxRequest(command.url, command);
请问在worker中除了数据的处理 能不能发请求呢?