再谈JavaScript线程


Posted in Javascript onJuly 10, 2015

代码判断一:

<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对象而报脚本错误 。

再谈JavaScript线程

        如果我们需要连续执行多个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标签。

今天比较累了,想睡觉了,先写这么多吧。

Javascript 相关文章推荐
基于Asp.net与Javascript控制的日期控件
May 22 Javascript
Package.js  现代化的JavaScript项目make工具
May 23 Javascript
js实现用户注册协议倒计时的方法
Jan 21 Javascript
jQuery实现非常实用漂亮的select下拉菜单选择效果
Nov 06 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
Jan 21 Javascript
angularJS 如何读写缓冲的方法(推荐)
Aug 06 Javascript
js实现年月日表单三级联动
Apr 17 Javascript
微信小程序之绑定点击事件实例详解
Jul 07 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
Jan 31 Javascript
vue.js实现三级菜单效果
Oct 19 Javascript
ES5新增数组的实现方法
May 12 Javascript
Vue项目打包编译优化方案
Sep 16 Javascript
javascript实现判断鼠标的状态
Jul 10 #Javascript
javascript检查浏览器是否已经启用XX功能
Jul 10 #Javascript
javascript实现确定和取消提示框效果
Jul 10 #Javascript
javascript实现的简单的表单验证
Jul 10 #Javascript
jQuery原生的动画效果
Jul 10 #Javascript
简述Jquery与DOM对象
Jul 10 #Javascript
JavaScript声明变量名的语法规则
Jul 10 #Javascript
You might like
PHP生成便于打印的网页
2006/10/09 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
php的SimpleXML方法读写XML接口文件实例解析
2014/06/16 PHP
详解php比较操作符的安全问题
2015/12/03 PHP
Yii2下session跨域名共存的解决方案
2017/02/04 PHP
JavaScript学习笔记记录我的旅程
2012/05/23 Javascript
JS如何判断移动端访问设备并解析对应CSS
2013/11/27 Javascript
Boostrap入门准备之border box
2016/05/09 Javascript
微信小程序 选择器(时间,日期,地区)实例详解
2016/11/16 Javascript
jQuery修改DOM结构_动力节点Java学院整理
2017/07/05 jQuery
JS数组操作之增删改查的简单实现
2017/08/21 Javascript
js中bool值的转换及“&amp;&amp;”、“||”、 “!!”详解
2017/12/21 Javascript
JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
2018/07/27 Javascript
vue工程全局设置ajax的等待动效的方法
2019/02/22 Javascript
vue插槽slot的简单理解与用法实例分析
2020/03/14 Javascript
浅谈vue生命周期共有几个阶段?分别是什么?
2020/08/07 Javascript
[01:29]2017 DOTA2国际邀请赛官方英雄手办展示
2017/03/18 DOTA
python实现在无须过多援引的情况下创建字典的方法
2014/09/25 Python
Django框架下在视图中使用模版的方法
2015/07/16 Python
使用Python+Splinter自动刷新抢12306火车票
2018/01/03 Python
解决Python安装后pip不能用的问题
2018/06/12 Python
pytorch中如何使用DataLoader对数据集进行批处理的方法
2019/08/06 Python
应聘自荐书
2013/10/08 职场文书
车间组长岗位职责
2013/12/20 职场文书
面试后感谢信
2014/02/01 职场文书
英文推荐信格式范文
2014/05/09 职场文书
志愿者活动总结报告
2014/06/27 职场文书
知识就是力量演讲稿
2014/09/13 职场文书
党委书记群众路线对照检查材料思想汇报
2014/10/04 职场文书
房产协议书范本
2014/10/18 职场文书
高中开学感言
2015/08/01 职场文书
《所见》教学反思
2016/02/23 职场文书
(开源)微信小程序+mqtt,esp8266温湿度读取
2021/04/02 Javascript
python中%格式表达式实例用法
2021/06/18 Python
《遗弃》开发商删推文要跑路?官方回应:还在开发
2022/04/03 其他游戏
java实现面板之间切换功能
2022/06/10 Java/Android