再谈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 相关文章推荐
JavaScript面向对象编程
Mar 02 Javascript
JavaScript使用IEEE 标准进行二进制浮点运算产生莫名错误的解决方法
May 28 Javascript
Seajs的学习笔记
Mar 04 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
Aug 19 Javascript
JS获取图片lowsrc属性的方法
Apr 01 Javascript
3种js实现string的substring方法
Nov 09 Javascript
详解JavaScript的AngularJS框架中的作用域与数据绑定
Mar 04 Javascript
Bootstrap零基础入门教程(三)
Jul 18 Javascript
bootstrap vue.js实现tab效果
Feb 07 Javascript
swiper Scrollbar滚动条组件详解
Sep 08 Javascript
LayUi使用switch开关,动态的去控制它是否被启用的方法
Sep 21 Javascript
多个Vue项目部署到服务器的步骤记录
Oct 22 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
php2html php生成静态页函数
2008/12/08 PHP
PHP初学者最感迷茫的问题小结
2010/03/27 PHP
php中防止伪造跨站请求的小招式
2011/09/02 PHP
解析百度搜索结果link?url=参数分析 (全)
2012/10/09 PHP
详解PHP神奇又有用的Trait
2019/03/25 PHP
PHP实现提高SESSION响应速度的几种方法详解
2019/08/09 PHP
JS中style属性
2006/10/11 Javascript
javascript function调用时的参数检测常用办法
2010/02/26 Javascript
单独使用CKFinder选择图片的方法
2010/08/21 Javascript
Jquery 跨域访问 Lightswitch OData Service的方法
2013/09/11 Javascript
脚本合并提升javascript性能示例
2014/02/24 Javascript
浅谈JavaScript中定义变量时有无var声明的区别
2014/08/18 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
深入浅析JavaScript系列(13):This? Yes,this!
2016/01/05 Javascript
jQuery Mobile动态刷新页面样式的实现方法
2016/05/28 Javascript
jQuery轮播图效果精简版完整示例
2016/09/04 Javascript
HTML5基于Tomcat 7.0实现WebSocket连接并实现简单的实时聊天
2016/10/31 Javascript
js实现密码强度检验
2017/01/15 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
js 获取json数组里面数组的长度实例
2017/10/31 Javascript
收集前端面试题之url、href、src
2018/03/22 Javascript
Vue.js中关于侦听器(watch)的高级用法示例
2018/05/02 Javascript
基于jQuery.i18n实现web前端的国际化
2018/05/04 jQuery
了解ESlint和其相关操作小结
2018/05/21 Javascript
ionic grid(栅格)九宫格制作详解
2018/06/30 Javascript
Vue打包后访问静态资源路径问题
2019/11/08 Javascript
用vite搭建vue3应用的实现方法
2021/02/22 Vue.js
由浅入深讲解python中的yield与generator
2017/04/05 Python
画pytorch模型图,以及参数计算的方法
2019/08/17 Python
Python线程指南分享
2019/11/19 Python
canvas像素画板的实现代码
2018/11/21 HTML / CSS
FC-Moto丹麦:欧洲最大的摩托车服装和头盔商店之一
2019/08/20 全球购物
医院后勤自我鉴定
2013/10/13 职场文书
会计主管岗位职责
2014/01/03 职场文书
心得体会的写法
2014/09/05 职场文书
JS的深浅复制详细
2021/10/16 Javascript