JavaScript高手转正学习(3)-定时器

时间: 2015-11-17 00:00 栏目: JavaScript 浏览: 7530 赞: 20 踩: 25 字体:

以下为本篇文章全部内容:

大家好,我叶子,接下来继续讲一讲 Js的定时器。
JS 的定时器也是在学习JS中至关重要的一步,可能很多人用过这个定时器,但是对这个定时器的使用可能还会存在一些误区。这里 我准备花1篇来专门讲关于JS的定时器。

时间控制流程的函数如下 
     setInterval();     //定时执行 如每隔多少毫秒执行1次
     setTimeout();     //延时执行 如过多少毫秒后执行

     setImmediate();   //延时执行 ,当加载的代码执行完后 接着执行
     nextTick(); //nodejs使用的 延时执行 在nodejs 中 和 setImmediate 功能类似
  

    而  setImmediate 和 nextTick 在执行顺序上还是有一些不同的 nextTick 是并行异步执行的 而 setImmediate 是 串行 顺序执行的


    还有需要注意的这些清理函数

   clearInterval();    

   clearTimeout(); 

   clearImmediate();


  1 我们先做一个例子: 鼠标移到div上后 精度条 开始加载的效果。

<div id="loadlayout" style=" width: 400px; height: 50px; border: 1px solid #888">
    <div id="load" style="width: 0px; height: 50px; background: #090; float: left;"></div>
</div>

<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script>
    (function ($) {
        $('#loadlayout').on('mouseover', function () {
            var pt = 0;
            var go = function () {
                console.log(pt);
                pt++;
                $('#load').css('width', pt + '%');
                if (pt < 100) {
                    setTimeout(go, 100);
                }
            };
            setTimeout(go, 100);
        });
    })(jQuery);
</script>

在这个效果中 我们似乎觉得是没有问题的,但是细心的人就会发现,如果多次滑过 后 这个效果就会变得极其闪烁,那么这个问题是怎么形成的呢?
有些朋友说 我不用这个 setTimeout 换 clearInterval 到100后清理即可。于是建议我改代码成这样.

<div id="loadlayout" style=" width: 400px; height: 50px; border: 1px solid #888">
    <div id="load" style="width: 0px; height: 50px; background: #090; float: left;"></div>
</div>

<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script>
    (function ($) {
        $('#loadlayout').on('mouseover', function () {
            var pt = 0;
           var timer= setInterval(function () {
                console.log(pt);
                pt++;
                $('#load').css('width', pt + '%');
                if (pt >= 100) {
                  window.clearInterval(timer);
                }
            }, 100);
        });
    })(jQuery);
</script>

  视乎好像已经是到100 后清理了~~ 就没有问题了,可是还是出现闪烁的问题。然而照成这种闪烁 的原因 是因为 每移动一次鼠标经过 就会触发一个异步工作纤程去执行这个事件,而 同时有多个纤程在修改这这个 #load 的宽度。它被不同的纤程数据修改着!
这个问题 在很多初学者中都会经常碰到! 为了彻底解决这个问题~我们一旦要使用 这个定时器时 一定要注意 它可能会被多次触发!!

我们把上面代码改成这样:

<div id="loadlayout" style=" width: 400px; height: 50px; border: 1px solid #888">
    <div id="load" style="width: 0px; height: 50px; background: #090; float: left;"></div>
</div>

<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script>
    (function ($) {
        var timer=null;
        $('#loadlayout').on('mouseover', function () {
            var pt = 0;
           if(timer) { window.clearInterval(timer); timer=null;}
           timer= setInterval(function () {
                console.log(pt);
                pt++;
                $('#load').css('width', pt + '%');
                if (pt >= 100) {
                    window.clearInterval(timer); timer=null;
                }
            }, 100);
        });
    })(jQuery);
</script>


2 接着我们讲讲计时器改什么时候使用

我在编程中是会尽量避免定时器的使用的 使用越少代码完整性越高,但是 我看多过很多人在书写JS代码是为了达到延时或者是等待某个啥的时候 做了一些定时器。

例如  
某程序员 为一个 img 设置了 src 但是 想获取到这个 图片的高宽,这个时候他想到了使用定时器了!!

<img/>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script>
     (function ($) {
        
        var img=$('img').attr('src','http://www.sunnyos.com/public/home/images/default.jpg');
        console.log(img.width());//显然得不到结果
        //某程序员这样做
        setTimeout(function(){
            console.log(img.width());
        },500);
        
    })(jQuery);
</script>

虽然这样也是可以得到高的,但是 谁都不敢保证500毫秒就能加载到图片,如果网速慢一点了呢? 如果网速快1点 也要等待500毫秒也不合适。
所以类似上面的代码 是不适合用 定时器去执行的 应避免滥用定时器,而多注重事件通知。

再有一种请求下 比如 你不需要 监听 body  的 load 事件 或者 body 已经 load 完成了!!
然而 你可能要加入一些代码 加入的代码不知道是多少个文件 那么这个时候 延迟执行就起到好处了!!

延迟执行  setImmediate 这个代码总在最后才执行



<script src="a.js" type="text/javascript"></script>
<script src="b.js" type="text/javascript"></script>
<script src="c.js" type="text/javascript"></script>
....
....
<script src="n.js" type="text/javascript"></script>



我们等不到最后一个文件执行 或者说我们不知道最后一个文件是哪个。但是我们希望加载完成后 执行我们的一些操作 这个时候我们可以用延迟执行

setImmediate(function(){});



未完待续...