【HTML5】webworker简介

webworker的作用

让web应用程序具备多线程处理能力,常用来处理一些比较耗时的任务。假设我们的应用上有个纯前端实现的马赛克滤镜,我们知道图像处理,尤其是大图片的处理通常是比较耗费时的,随时都有可能让你的页面卡个几秒,这期间UI线程会被阻塞,这意味着用户需要对着一个无法进行任何交互的页面抓狂,这是无法容忍的。这个时候,webworker就发挥它的用处了,图像处理神马的后台悄悄进行就行了,用户可以继续浏览器美图神马的(奸笑),时间到,打了马赛克的妹子图片就呈现在用户面前了

 

简单例子

下面的demo涉及两个文件,分别是demo.html、worker.js。代码很简单,但已经包含了webworker最重要的几个内容,细节在后面再展开:

  1. worker创建:new Worker(XX)
  2. 消息发送:postMessage
  3. worker事件:消息接收(message)、出错处理(error)
  4. 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演示内容:

  1. demo.html里创建一个worker WW加载worker.js,并向其发送消息:这是'webworker的demo!'
  2. worker.js 收到W传给它的消息,并在该消息末尾加上'--worker.js里的附加信息'后,再回传给W
  3. 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,需要注意的有以下几点:

  1. 子worker的路径必须与父网页同源
  2. 子worker的路径相对于父worker解析,而不是父网页
  3. webkit(chrome 25,safari 6)内核的浏览器尚不支持子worker,无力吐槽

 

需要注意的坑

前端科普文必然有的一块内容,肿么突然有点心酸~~Fraky大大已经总结了不少,就偷懒下了,链接如下可猛点击:http://www.cnblogs.com/_franky/archive/2010/11/23/1885773.html

 

待解决

  1. 调试问题:chrome最新版本也仍不支持子线程调试??(已支持,开发者工具-source-workers)
posted @ 2013-03-28 00:58  程序猿小卡  阅读(2923)  评论(2编辑  收藏