一、webWorker之初体验

"setTimeout那些事儿"中,说到JavaScript是单线程。也就是同一时间只能做同一事情。

也好理解,作为浏览器脚本语言,如果JavaScript不是单线程,那么就有点棘手了。比如,与用户交互或者对DOM进行操作时,在一个线程上修改某个DOM,另外的线程删除DOM,这时浏览器该如何抉择呢?

所以,JavaScript是单线程也是有背景的。

如下:

<!DOCTYPE html>
<head>
<title>singleThread</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<script>
//添加到任务队列中,待同步任务所处的‘执行栈’执行完毕,1秒后执行任务队列中的这个匿名函数
setTimeout(function(){
console.log('come on');
},1000);
//只要不关闭该alert,‘执行栈’就没结束,从而也就不会进入到任务队列中
alert('waiting');
</script>
</body>
</html>

但,HTML5引入了一个工作线程(webWorker)的概念。它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的响应。

简而言之,就是允许JavaScript创建多个线程,但是子线程完全受主线程控制,且不得操作DOM

从而,可以用webWorker来处理一些比较耗时的计算。

如下,主页面:

<!DOCTYPE html>
<head>
<title>worker</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script>
function init(){
//创建一个Worker对象,并向它传递将在新线程中执行的脚本url
var worker = new Worker('worker.js');
//接收worker传递过来的数据
worker.onmessage = function(event){
document.getElementById('result').innerHTML+=event.data+"<br/>" ;
};
};
</script>
</head>
<body onload = "init()">
<div id="result"></div>
</body>
</html>

下面是worker.js的内容:

var i = 0;
function timedCount(){
for(var j = 0, sum = 0; j < 100; j++){
for(var i = 0; i < 100000000; i++){
sum+=i;
};
};
//将得到的sum发送回主线程
postMessage(sum);
};
//将执行timedCount前的时间,通过postMessage发送回主线程
postMessage('Before computing, '+new Date());
timedCount();
//结束timedCount后,将结束时间发送回主线程
postMessage('After computing, ' +new Date());

上面代码执行的流程是:创建的worker对象,并用onmessage方法接收worker.js里面postMessage传递过来的数据(event.data),并将数据追加到div#result中。

所以,执行上面的代码结果如下:

 图一

待worker.js中的timedCount方法运算完后,执行postMessage操作,向主线程传数据,得图二。期间,并不影响主线程的运作。

图二

二、webWorker之常用API

接下来,再来看看关于worker的常用API:

1、postMessage(data)

子线程与主线程之间互相通信使用方法,传递的data为任意值。

//worker = new Worker('url');
//worker.postMessage传递给子线程数据,对象
worker.postMessage({first:1,second:2}); //子线程中也可以使用postMessage,如传递字符串
postMessage(‘test’);

2、terminate()

主线程中终止worker,此后无法再利用其进行消息传递。注意:一旦terminate后,无法重新启用,只能另外创建。

//worker = new Worker('url');
worker.terminate();

如,主页面:

<!DOCTYPE html>
<head>
<title>worker</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script>
function init(){
var worker = new Worker('worker.js');
//每隔100毫秒,向子线程传递{name: 'monkey'}信息
setInterval(function(){
worker.postMessage({name: 'monkey'});
},100);
//当主线程worker收到来自子线程的消息后,触发message事件
worker.onmessage = function(event){
document.getElementById('result').innerHTML+=event.data+"<br/>" ;
//主线程使用terminate方法中断与子线程来往,在浏览器中只能显示一次event.data
worker.terminate();
};
};
</script>
</head>
<body onload = "init()">
<div id="result"></div>
</body>
</html>

子线程worker.js代码:

//当主线程发来信息后,触发该message事件
onmessage = function(event){
//向主线程发送event.data.name信息
postMessage(event.data.name);
};

3、message

当有消息发送时,触发该事件。且,消息发送是双向的,消息内容可通过data来获取。

message使用,可见terminate中的demo

4、error

出错处理。且错误消息可以通过e.message来获取。

如下:

//worker = new Worker('url');
worker.onerror = function(e){
//打印出错消息
console.log(e.message);
//中断与子线程的联系
worker.terminate();
}

另:worker线程从上到下同步运行它的代码,然后进入异步阶段来对事件及计时器响应,如果worker注册了message事件处理程序,只要其有可能触发,worker就一直在内存中,不会退出,所以通信完毕后得手动在主线程中terminate或者子线程中close掉但如果worker没有监听消息,那么当所有任务执行完毕(包括计数器)后,他就会退出。

三、worker上下文

先看下面这段代码:

主页面:

<!DOCTYPE html>
<head>
<title>worker</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script>
function init(){
var worker = new Worker('worker.js');
//接收消息事件
worker.onmessage = function(event){
console.log(event.data);
};
//错误信息事件
worker.onerror = function(e){
console.log('erro: ' + e.message);
//终止线程
worker.terminate();
};
};
</script>
</head>
<body onload = "init()"> </body>
</html>

worker.js

//window对象的alert方法
alert(1);
onmessage = function(event){
//向主线程发送event.data.name信息
postMessage(event.data.name);
};

执行上面代码结果:

为什么会这样呢?原因是alert为window对象的方法,所以会报错undefined。

worker.js执行的上下文,与主页面html执行时的上下文并不相同,最顶层的对象并不是window,woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。
WorkerGlobalScope作用域下的常用属性、方法如下:

1、self

  我们可以使用 WorkerGlobalScope 的 self 属性来或者这个对象本身的引用

2、location

  location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,它表示用于初始化这个工作线程的脚步资源的绝对 URL,即使页面被多次重定向后,这个 URL 资源位置也不会改变。

3、close

  关闭当前线程,与terminate作用类似

4、importScripts

  我们可以通过importScripts()方法通过url在worker中加载库函数

5、XMLHttpRequest

  有了它,才能发出Ajax请求

6、setTimeout/setInterval以及addEventListener/postMessage

四、关于worker

我们可以做什么:

  1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信

  2.可以在worker中通过importScripts(url)加载另外的脚本文件

  3.可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()

  4.可以使用XMLHttpRequest来发送请求

  5.可以访问navigator的部分属性

局限性:

  1.不能跨域加载JS

  2.worker内代码不能访问DOM

  3.各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行

  4.IE这个新特性

 

webWorker的更多相关文章

  1. 浅谈webWorker

    一.webWorker之初体验 在"setTimeout那些事儿"中,说到JavaScript是单线程.也就是同一时间只能做同一事情. 也好理解,作为浏览器脚本语言,如果JavaS ...

  2. WebWorker的importScripts方法

    简述 在<JavaScript高级程序设计(第三版)>中,提到WebWorker的importScripts方法是异步执行的,然而在 另一本书<Javascript权威指南>中 ...

  3. HTML5系列四(WebWorker、地理定位)

    WebWorker简单应用 先从一个简单例子说起,计算数值加法 <script> var worker = new Worker('sumCalculate.js'); worker.on ...

  4. HTML5学习总结-06 WebWorker

    一 WebWorkder 它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的响应.简而言之,就是允许JavaScript创建多个线程,但是子线程完全 ...

  5. WebWorker SharedWorker ServiceWorker

    WebWorker 是什么? 为 JavaScript 引入线程技术 不必再用 setTimeout().setInterval().XMLHttpRequest 来模拟并行 Worker 利用类似线 ...

  6. web-worker计数器,根据输入时间统计次数

    1.用web-worker实现:另起一个线程,将计数工作运行在后台的JavaScript文件,并返回累加后的结果. 该js文件运行于后台,独立于其他脚本,不会影响页面的性能.html页面可以继续做任何 ...

  7. WebWorker实战使用

    总体来说webworker解决了阻塞主线程问题,但是还没解决高性能计算的问题 WebWorker整体介绍 https://developer.mozilla.org/zh-CN/docs/Web/AP ...

  8. H5新特性之webWorker

    众所周知javascript是单线程语言,这就是js开发难度较低的原因了,因为不需要解决多线程的资源共享问题(例如死锁),但是单线程性能并不好,因此多了一个webWorker实现js的多进程来提升js ...

  9. 异步编程Promise/Deferred、多线程WebWorker

    长期以来JS都是以单线程的模式运行的,而JS又通常应用在操作用户界面和网络请求这些任务上.操作用户界面时不能进行耗时较长的操作否则会导致界面卡死,而网络请求和动画等就是耗时较长的操作.所以在JS中经常 ...

  10. WebWorker 中将已处理好的 VDOM 数据提交主线程渲染 DOM

    上篇文章讲了 WebWorker 的简单用法,其实网上很多类似的文章,我写的也比较垃圾.不会的建议可以网上看比较好点的资料. 这里我会先讲下我的大致思路.然后会贴上一堆不实用的垃圾代码供参考. Web ...

随机推荐

  1. 【第一次玩Travis CI】终于弄好了我的马鸭

    真是不容易,我都要哭了.熬了半天终于弄完了!! 终于可以坐这儿挺会小曲,写写感受了. 作为一个程序写的不咋滴的程序员,倒是特别喜欢写博客,也是绝了. 高三的时候,用OneNote,后来转到Lofter ...

  2. MySQL多实例.md

    MySQL5.7多实例配置 数据库实例1配置文件 # cat /etc/my.cnf [mysqld] datadir=/data/mysql port=3306 socket=/tmp/mysql. ...

  3. css里颜色的那些事儿(合法颜色值)

    css中主要有六种方法指定颜色: 1.十六进制颜色 2.RGB颜色 3.RGBA颜色 4.HSL色彩 5.HSLA颜色 6.预定义/跨浏览器的颜色名称 前三种是我们最常见的,也是用的最多的,而后三种对 ...

  4. hadoop学习通过虚拟机安装hadoop完全分布式集群

    要想深入的学习hadoop数据分析技术,首要的任务是必须要将hadoop集群环境搭建起来,可以将hadoop简化地想象成一个小软件,通过在各个物理节点上安装这个小软件,然后将其运行起来,就是一个had ...

  5. ethereum/EIPs-170 Contract code size limit

    eip title author type category status created 170 Contract code size limit Vitalik Buterin Standards ...

  6. oracle数据库flashback系列--闪回数据库在dataguard中的使用

    很多人在学习flashback database这个oracle技术的时候,都会有一个疑问,就是如果我只有一个数据库作为生产库的话,是否有这样的业务需求导致我们要把数据库闪回到以前的时间点?以及这样做 ...

  7. 搞死人的contextRoot;weblogic9.2

    默认情况下: 两个app-deployment同时部署到了一台weblogic服务器的同一个domain下面的时候 /mysite/www/www/WEB-INF/weblogic.xml /mysi ...

  8. leetcode650—2 Keys Keyboard

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...

  9. 开关电源五种PWM反馈控制模式

    开关电源五种PWM反馈控制模式 来源:--作者:--浏览:178时间:2016-08-10 14:18 关键词: 1 引言 PWM开关稳压或稳流电源基本工作原理就是在输入电压变化.内部参数变化.外接负 ...

  10. Loopback接口用途---用作管理地址。

    Loopback接口的优点是永远不会down点,不管是链路断开还是网卡损坏.因而loopback接口有很高健壮性. 但是loopback并非实际网口,外部设备要与该口通信,必须经过实际口的路由实现. ...