继上篇讨论了一些关于JavaScript线程的知识,我们不妨回过头再看看,是不是JavaScript就不能多线程呢?看下面一段很简单的代码(演示用,没考虑兼容问题):

代码判断一:

<div id="div">
click me
</div> <script>
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<999999999;i++){
console.log(i);
}
</script>

执行之,不出意外的话所有浏览器都会卡死,因为上面的for循环次数太多了,非常耗费CPU资源,而基于JavaScript单线程的事实,浏览器UI渲染被挂起而导致假死。

现在问题来了,我就是想要实现上述代码,怎么办?

Concurrent.Thread.js

该类库实质上还是使用setTimeout来实现一个“假的多线程”。在HTML5 WebWorker问世之前是一个很好的选择。比如我们要实现上述“代码片段一”,可以这样写(点我下载类库):

代码片段二:

<div id="div">
click me
</div>
<script src="Concurrent.Thread.js"></script>
<script>
Concurrent.Thread.create(function(){
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<9999999;i++){
console.log(i);
}
});
</script>

通过该类库提供的create方法可以创建一个“新线程”。另外,给script标签的type属性设置为 text/x-script.multithreaded-js 也可以实现同样的效果:

代码片段三:
<div id="div">
click me
</div>
<script src="Concurrent.Thread.js"></script>
<script type="text/x-script.multithreaded-js">
var div=document.getElementById("div");
div.addEventListener('click',function(){
alert('You have clicked me!');
});
for(var i =0; i<9999999;i++){
console.log(i);
}
</script>

WebWorker

针对以上浏览器卡死这种糟糕的用户体验,HTML5怎么会熟视无睹呢?

下面我们用经典的斐波那契数列来做测试:

代码片段四:

主页面:
<div id="div"></div>
<script>
window.onload=function(){
var div=document.getElementById("div");
if(typeof(Worker)!=="undefined"){//在创建WebWorker之前,先判断浏览器是否支持
        console.log("Start calculating....");
var time1= new Date()*1;//获得当前时间戳
var worker=new Worker("fibonacci.js");//创建WebWorker对象,并传递在新线程中将要执行的脚本的路径
worker.onmessage=function(e){ //监听从新线程发送过来的数据
div.innerHTML=e.data;
var time2=new Date()*1;
console.log("time spend:"+(time2-time1)+"ms");
}
        
worker.postMessage(36);//向新线程发送数据
}else{
alert("Your browser do not support WebWoker");
}
}
</script> fibonacci.js:
var fibonacci=function (n){
return n<3?n:(arguments.callee(n-1)+arguments.callee(n-2));
}
onmessage=function(e){
var num=parseInt(e.data,10);
postMessage(fibonacci(num));//向主页面发送数据
}

基本的使用方法已在代码中做注释了,查看控制台,可以看见很快就打印出执行时间了。所以我们得出的结论是:WebWorker适合在前端执行复杂的大量的计算。需要注意的是,WebWorker不支持跨域,本地测试还是用http协议,不要用file协议,否则不能创建Worker对象而报脚本错误 。

如果我们需要连续执行多个postMessage操作,最好不要work.postMessage一直写,像这样:

worker.postMessage(36);

worker.postMessage(36);

worker.postMessage(36);

因为此时只有一个WebWorker实例,postMessage会顺序执行而不是异步执行,就不能充分发挥它的性能了。可以通过创建多个WebWorker实例来发送数据。

需要注意的几点事项有:

1、我们观察到WebWorker通过接受一个url来创建一个worker,而jsonp的实现原理就是通过动态插入script标签加载数据,那我们尝试用WebWorker来实现同样的事情不是更好吗?因为WebWorker是多线程的,没有阻塞,岂不美哉?但实际上经过实验,我们发现WebWorker表现并不如意。所以这并不是它擅长的事,我们还是不要让它越俎代庖的好。

2、WebWorker在接受其他来源信息的时候,其实也给站点的安全带来了隐患,如果接收不明来源的脚本信息,可能会导致XSS注入攻击。所以这点需要防范,其实我们上面例子中使用innerHTML是不安全的,可以使用innerText或现代浏览器提供的textContent来替代,以过滤掉html标签。

  今天比较累了,想睡觉了,先写这么多吧。有兴趣深入了解的同学可以查看这个地址了解更多知识:深入了解HTML5工作线程

再看JavaScript线程的更多相关文章

  1. 再看GS线程

    再看GS线程 void GameServer::ProcessThreadTry() { ; packet rcvPkt; rcvPkt.data = * ]; //该事件工厂主要创建了两个定时器1. ...

  2. 再看javascript执行上下文、变量对象

    突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文.变量对象.作用域.this等语言细节.内容短小而精悍,文风直白而严谨,读完有酣畅淋漓 ...

  3. setTimeout setInterval 区别 javascript线程解释

    原文:http://www.iamued.com/qianduan/1645.html 今天看到这篇文章,学到了不少东西 特此发出来 和大家分享 JavaScript的setTimeout与setIn ...

  4. javascript线程解释(setTimeout,setInterval你不知道的事)---转载

    在工作中,可能我们经常遇到在有很多 setInterval 的页面, 再手动触发 setTimeout 的时候经常失败, 尤其是 jquery做动画的时候,一些渐入溅出的东西,很多东西都不被触发……, ...

  5. javascript线程解释(setTimeout,setInterval你不知道的事)

    john resig写的一篇文章: 原文地址:http://ejohn.org/blog/how-javascript-timers-work/ 作为入门者来说,了解JavaScript中timer的 ...

  6. JavaScript线程

    JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不少人都深有同感, 例如 setTimeout( ...

  7. [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)【转】

    (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我就迷糊了.为什么只有 ...

  8. Android菜鸟的成长笔记(17)—— 再看Android中的Unbounded Service

    原文:Android菜鸟的成长笔记(17)-- 再看Android中的Unbounded Service 前面已经写过关于startService(Unbounded Service)的一篇文章:&l ...

  9. Javascript:看 Javascript 规范,学 this 引用,你会懂的。

    目录 背景this待分析程序先看一个语言规范方法调用备注 背景返回目录 Javascript 的 this 是我的心病,多数情况下知道其运行结果,个别变态的场景下,就给不出解释了,昨天一次偶然的机遇让 ...

随机推荐

  1. lucene创建索引简单示例

    利用空闲时间写了一个使用lucene创建索引简单示例, 1.使用maven创建的项目 2.需要用到的jar如下: 废话不多说,直接贴代码如下: 1.创建索引的类(HelloLucene): packa ...

  2. Add-VMNetworkAdapterAcl(添加访问控制列表)

    Add-VMNetworkAdapterAclCreates an ACL to apply to the traffic through a virtual machine network adap ...

  3. 【转】http响应状态代码含义及跳转的类型

    转自:http://www.west263.com/info/html/caozuoxitong/FreeBSD/20090513/123479.html 当我们在因特网遨游的时候,每天都会看到诸如5 ...

  4. [GIF] GIF Loop Coder - Introduction

    Introducing the program, GIF Loop Coder, which allows you to make looping animated gifs (and other t ...

  5. Java从设计模式[本场比赛状态转换武器]状态分析(State)模式

    如果我们正在做一个实时战略游戏.我们设计了一个武器,他制作只是当步兵,但他能够切换武器.第一个开关会变成弓箭手,第二个开关导通控股装甲盾牌,第三开关变成步兵--如何实现这一目标切换机构?我们开始思考, ...

  6. 【点滴积累】通过特性(Attribute)为枚举添加更多的信息

    转:http://www.cnblogs.com/IPrograming/archive/2013/05/26/Enum_DescriptionAttribute.html [点滴积累]通过特性(At ...

  7. qt软键盘输入

      characterapplicationsignalqt输入法object 1.从QInputContext派生自己的InputContext类 ,例如: class MyInputPanelCo ...

  8. Mac OS X 如何设置默认浏览器

    有时候我们不希望在 Mac 中点击任何连接都打开的是 Safari,这需要修改默认浏览器设置,在 Mac OS X 中如何设置默认浏览器呢? 打开 Safari 的偏好设置,在「通用」选项卡中有「默认 ...

  9. eclipse 中修改 M2_REPO的值--转载

    从eclipse中增加了maven2的插件之后,maven默认的本地库的路径是${user}/.m2/repository/下,一般windows用户的操作系统都安装在C盘,所以这个目录 下的jar包 ...

  10. codeblocks 更改颜色主题

    Code::Blocks是一款优秀的C/C++编辑器,但默认的颜色为白底黑字,并且没有自带更多的主题配置.因此,各种颜色主题需要手动配置. 首先关闭codeblocks软件. 下载文件colour_t ...