再谈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 相关文章推荐
jquery $.ajax入门应用一
Nov 19 Javascript
js数字转换为float,取N位小数
Feb 08 Javascript
一款基于jQuery的图片场景标注提示弹窗特效
Jan 05 Javascript
javascript中Array()数组函数详解
Aug 23 Javascript
Bootstrap每天必学之折叠(Collapse)插件
Apr 25 Javascript
bootstrap和jQuery.Gantt的css冲突 如何解决
May 29 Javascript
jQuery通过ajax请求php遍历json数组到table中的代码(推荐)
Jun 12 Javascript
jQuery常用样式操作实例分析(获取、设置、追加、删除、判断等)
Sep 08 Javascript
jQuery子元素过滤选择器用法示例
Sep 09 Javascript
angularjs 页面自适应高度的方法
Jan 17 Javascript
node.js基础知识小结
Feb 26 Javascript
JS实现DOM删除节点操作示例
Apr 04 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 日志缩略名的创建函数代码
2010/05/26 PHP
PHP+SQL 注入攻击的技术实现以及预防办法
2010/12/29 PHP
PHP数据流应用的一个简单实例
2012/09/14 PHP
解析php框架codeigniter中如何使用框架的session
2013/06/24 PHP
php实现算术验证码功能
2018/12/05 PHP
PHP实现关键字搜索后描红功能示例
2019/07/03 PHP
PHP中散列密码的安全性分析
2019/07/26 PHP
PHP基于phpqrcode类生成二维码的方法示例详解
2020/08/07 PHP
JavaScript Accessor实现说明
2010/12/06 Javascript
Jquery 监视按键,按下回车键触发某方法的实现代码
2014/05/11 Javascript
jQuery实现hover合成事件的方法
2015/08/06 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
2016/09/01 Javascript
AngularJS中一般函数参数传递用法分析
2016/11/22 Javascript
使用原生js写ajax实例(推荐)
2017/05/31 Javascript
jQuery Collapse1.1.0折叠插件简单使用
2017/08/28 jQuery
使用ionic(选项卡栏tab) icon(图标) ionic上拉菜单(ActionSheet) 实现通讯录界面切换实例代码
2017/10/20 Javascript
vue2.0 移动端实现下拉刷新和上拉加载更多的示例
2018/04/23 Javascript
vue-router 源码实现前端路由的两种方式
2018/07/02 Javascript
使用express获取微信小程序二维码小记
2019/05/21 Javascript
详解Vue Cli浏览器兼容性实践
2020/06/08 Javascript
微信小程序学习之自定义滚动弹窗
2020/12/20 Javascript
[00:34]DOTA2上海特级锦标赛 VG战队宣传片
2016/03/04 DOTA
python基础教程之序列详解
2014/08/29 Python
Python Web框架Flask中使用七牛云存储实例
2015/02/08 Python
python3+PyQt5实现自定义窗口部件Counters
2018/04/20 Python
Python基于datetime或time模块分别获取当前时间戳的方法实例
2019/02/19 Python
python flask框架实现重定向功能示例
2019/07/02 Python
python 两个一样的字符串用==结果为false问题的解决
2020/03/12 Python
通过Canvas及File API缩放并上传图片完整示例
2013/08/08 HTML / CSS
小学师德师风整改措施
2014/10/27 职场文书
新郎新娘答谢词
2015/01/04 职场文书
2015年国庆节新闻稿
2015/07/18 职场文书
奖学金主要事迹范文
2015/11/04 职场文书
关于springboot配置druid数据源不生效问题(踩坑记)
2021/09/25 Java/Android
A22国内电台短波广播频率表
2022/05/10 无线电
Python find()、rfind()方法及作用
2022/12/24 Python