webworker的作用
让web应用程序具备多线程处理能力,常用来处理一些比较耗时的任务。假设我们的应用上有个纯前端实现的马赛克滤镜,我们知道图像处理,尤其是大图片的处理通常是比较耗费时的,随时都有可能让你的页面卡个几秒,这期间UI线程会被阻塞,这意味着用户需要对着一个无法进行任何交互的页面抓狂,这是无法容忍的。这个时候,webworker就发挥它的用处了,图像处理神马的后台悄悄进行就行了,用户可以继续浏览器美图神马的(奸笑),时间到,打了马赛克的妹子图片就呈现在用户面前了
简单例子
下面的demo涉及两个文件,分别是demo.html、worker.js。代码很简单,但已经包含了webworker最重要的几个内容,细节在后面再展开:
- worker创建:new Worker(XX)
- 消息发送:postMessage
- worker事件:消息接收(message)、出错处理(error)
- worker终止:terminate
demo.html里面的代码:
var worker = new Worker('worker.js');
worker.onmessage = function(evt){
alert('消息收到啦:'+ evt.data);
worker.terminate();
};
worker.onerror = function(e){
alert('demo出错了!出错原因是:' + e.message);
worker.terminate();
};
worker.postMessage('这是webworker的demo!');
worker.js里面的代码:
this.onmessage = function(evt){
postMessage(evt.data +'--worker.js里的附加信息');
};
demo演示内容:
- demo.html里创建一个worker W,W加载worker.js,并向其发送消息:这是'webworker的demo!'
- worker.js 收到W传给它的消息,并在该消息末尾加上'--worker.js里的附加信息'后,再回传给W
- W收到worker.js回传的消息,弹窗显示,然后把自己给终止掉
最终你会看到
消息收到啦:这是webworker的demo!--worker.js里的附加信息
常用API等简单介绍
1. worker创建
注意:引号里的url地址可以为绝对地址,或相对地址,但必须同源
var worker = new Worker('worker.js');
2. 常用API
possMessage(data)
data理论上可以为任意值,但保险起见最好还是传字符串,接收方需注册message事件老接收消息,如demo.html中
var worker = new Worker('worker.js');
terminate()
终止worker,此后无法再利用其进行消息传递等。需要注意:worker不会自行终止,一旦terminate,无法重新启用,只能另行创建。如demo.html中
worker.terminate();
3. 事件
message
一旦有消息发送,则会触发。消息的发送是双向的,消息的内容可通过data获取,如demo.html中,evt.data即为worker.js中传递过来的消息内容:
worker.onmessage = function(evt){
alert('消息收到啦:'+ evt.data);
worker.terminate();
};
error
出错处理,比如worker.js中出现语法错误、运行时错误之类的,就会触发,错误信息可通过e.message获得,如demo.html中
worker.onerror = function(e){
alert('demo出错了!出错原因是:' + e.message);
worker.terminate();
};
worker的上下文
刚刚接触web worker的童鞋,对于这点可能有些疑惑。我们可以先用下面这个小小的例子简单说明一下。还是之前的worker.js,只不过在最开头的时候加上了一句alert('hello world');
alert('hello'); //额外添加的语句
this.onmessage = function(evt){
postMessage(evt.data +'--worker.js里的附加信息');
};
于是,你会看到下面的弹窗内容
demo出错了!出错原因是:Uncaught ReferenceError: window is not defined
从上面的出错提示可以猜想:worker.js执行的上下文,与demo.html执行时的上下文并不相同,最顶层的对象的对象并不是window,无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。
woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,它具有属性/方法:
self
指向WorkerGlobalScope
inmoprScripts(XX[,XX, XX…])
加载外部脚本文件,理论上是按照加载它们的顺序执行(仅仅是理论上),且执行上下文与当前执行上下文一致,比如在worker.js里面
importScripts('subworker.js');
importScripts('a.js', 'b.js', 'c.js');
那么理论上,subworker.js、a.js、b.js、c.js应该是hi顺序执行的,这里就不举具体例子了。
close()
关闭当前线程,与terminate作用类似
location
返回当前worker的location信息,location.href为当前worker创建时指向的文件绝对路径
setTimeout/setInterval
没什么好介绍的
子worker的创建
可在当前woker环境下,通过new Worker(XX)方式创建子worker,需要注意的有以下几点:
- 子worker的路径必须与父网页同源
- 子worker的路径相对于父worker解析,而不是父网页
- webkit(chrome 25,safari 6)内核的浏览器尚不支持子worker,无力吐槽
需要注意的坑
前端科普文必然有的一块内容,肿么突然有点心酸~~Fraky大大已经总结了不少,就偷懒下了,链接如下可猛点击:http://www.cnblogs.com/_franky/archive/2010/11/23/1885773.html
待解决
- 调试问题:chrome最新版本也仍不支持子线程调试??(已支持,开发者工具-source-workers)