setTimeout和Web Workers解决耗时操作

2018-06-05  本文已影响103人  卓三阳

众所周知javascript是单线程的,特点就是容易出现阻塞。如果一段程序处理时间很长,很容易导致整个页面hold住。什么交互都处理不了怎么办?

复杂逻辑后端处理
html5的Web Workers
setTimeout

1.setTimeout
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<h1> this is a header</h1>
</body>
<script>
window.onload=function(){

  var processTime = 0;

  //1.常规操作
  // tcCircle();

  function tcCircle(){
    var arr = new Array(10);
    for(var i=0;i<arr.length;i++){
      process(arr[i]);
    }
    //页面标题栏一直转圈 且下面的语句迟迟无法执行,页面也无法加载
    console.log("long process finish!");
  }


  //2.执行setTimeout数组分块操作,利用setTimeout延时调用
  var arr = new Array(10);
  var i=0;
  var timer;

  timer=setTimeout(tcCircleUseSetTimeout,0);

  function tcCircleUseSetTimeout(){
     process(arr[i++]);
     if(i<10){
       //如果没处理完,下一次Event Loop继续处理
       // timer=setTimeout(tcCircleUseSetTimeout,0);
       timer=setTimeout(arguments.callee,0);
      }else{
        console.log("long process finish!");
      }
  }


  function process(ele){
    console.log("process"+(++processTime));
    //模拟长时间的处理过程
    sleep(1000);
  }

  //利用死循环模拟处理某个时间的过程
  function sleep(sleepTime){
    var start=new Date().getTime();
    while(true){
      if(new Date().getTime()-start>sleepTime){
        break;  
      }
    }
  }


}  
</script>
</html>

arguments.callee


2.工作线程Web Workers

Web Workers

Web Worker的基本原理就是在当前javascript的主线程中,使用Worker类加载一个javascript文件来开辟一个新的线程,起到互不阻塞执行的效果,并且提供主线程和新线程之间数据交换的接口:postMessage,onmessage。

index.html

<body>
<h1> this is a header</h1>
</body>
<script>
window.onload=function(){
if (window.Worker) {
   var worker =new Worker('javascripts/fibonacci.js');  
    worker.addEventListener('message', function(event) {
      var timer2 =new Date().valueOf();
      console.log( '结果:'+event.data, '时间:'+ timer2, '用时:'+ ( timer2  - timer1 ) );
    }, false);
   
    worker.postMessage(40);
    var timer1 = (new Date()).valueOf();
    console.log('开始计算fibonacci(40)','时间:'+ timer1 );
    
    console.log('这是在计算fibonacci(40)的时候执行', '时间:'+ new Date().valueOf());

  }
}  
</script>

fibonacci.js

var fibonacci =function(n) {
    return n <2? n : arguments.callee(n -1) + arguments.callee(n -2);
};

onmessage =function(event) {
    var n = parseInt(event.data, 10);
    postMessage(fibonacci(n));
};

结果:


res.png
WebWorker 可以做什么:

(1)可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
(2)可以在worker中通过importScripts(url)加载另外的脚本文件
(3)可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
(4)可以使用XMLHttpRequest来发送请求

说明:Ajax 和 Web Worker 都是异步执行的,似乎没有必要在Web Worker里调用Ajax,如果存在这种情况,Ajax 需要按照一个队列里数据排列的顺序同步发送请求,如果不想页面被阻塞,这种情况下可以使用Web Worker 并且需要在Web Worker里使用Ajax。

局限性:

(1)Web Worker 不支持跨域
(2)worker内不能访问DOM
(3)各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行
(4)无法访问 LocalStorage,和对 dom 元素的限制一样,因为读写 LocalStorage 是同步的,一定会引起 race condition


参考
浅析H5新增的Webworker对象

其他
HTML5 之 Web Worker
深入 HTML5 Web Worker 应用实践:多线程编程
WebWorker实战使用
聊聊 webworker

上一篇 下一篇

猜你喜欢

热点阅读