西红柿爱番茄

Feed Rss

Web Worker浅析

08.01.2010, Javascript, by .

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]

原理看起来很简单,但是在接触它的时候,有几个疑问在脑子里转:

  1. Worker类接收js文件的url为参数,是否可以接收js代码字符串呢?
  2. 如果外联的js文件处理的时间很长,这样主线程的Worker对象的onmessage和postMessage执行会不会报错?
  3. 会不会存在编码问题?

经过测试之后,答案一一揭晓:Worker类不能够接收js代码字符串,比如:”new Worker(‘onmessage=function…’)”;onmessage在这里是一种类似于click等的事件,它会在接收到数据之后触发,所以不用顾虑外联js文件处理的时间问题;因为Worker类的参数是一个url,它就会向服务器请求这个文件,发送一个HTTP请求,这里就又回归到Ajax的模式了,不过要注意编码问题。

还有一点需要注意的是:在外联js文件中,onmessage方法的声明方式千万别带上var,否则在Chrome,Safari,Opera下会失效,FF在有没有var都可以。

测试用例:《有var》,《无var

Web Worker浅析 有 7 条回应

  1. 您好~我是王培栋 最近一直在学习中~~我的QQ:654371743

  2. 这篇不错 西红柿总是先研究新东东.给大家分享..顶

  3. 第一次拜访,真的不错
    谢谢分享!!

  4. 引用: 在IE中模拟Worker | 西红柿青炒番茄

  5. 2010-10-25 在 12:53 stallboy

    如果你使用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对象。

  6. 2010-10-25 在 14:22 Supersha

    原来如此,哈哈……
    当时我也觉得奇怪,测试之后发现这个问题

  7. 2011-08-10 在 20:10 steveli

    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中除了数据的处理 能不能发请求呢?

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>