定时器

泄露秘密 提交于 2020-03-16 09:01:09

  本篇文章主要分别讲一下setInterval,setTimeout,setImmediate,requestAnimationFrame的使用及注意事项。

  一、 setInterval

    重复执行定时器,每隔一段时间就会去执行指定的函数。重复的执行。

    语法:如下

    参数:要执行的函数:当时间到了就会去执行这里的代码

       时间:间隔的时间,单位是ms。1s=1000ms。当第二个参数省略的时候,这个参数为0.

<script>
    setInterval(function () {
        要执行的代码
    }, 时间)
</script>

    事实上,除了前面两个参数,setInterval()方法还允许添加更多的参数,但是这个只有在ie9以上才支持。

<script>
    setInterval(function (a, b) {
        console.log(a + b) //2
    }, 2000, 1, 1)
</script>

  二、setTimeout

    延迟执行定时器:当延迟时间到达后,会执行指定的函数,这个函数只执行一次。

    语法:如下

<script>
    setTimeout(function(){
        当时间到达后,会执行这里的代码
    },时间);
</script>

    setTimeout的用法与setInterval完全一致,只不过是setTimeout只执行一次,setInterval执行多次。

例子:

<body>
    <script>
        window.onload = function () {
            var btn = document.getElementById('btn');
            var i = 0;
            btn.onclick = function () {
                /*
                第一种方法:
                setInterval(function () {
                    btn.innerHTML = i;
                    i++;
               }, 200);*/

                //注意:当函数在外面定义时,这里面调用只能写函数的名字不能加括号
                //第二种方法:
                setInterval(change, 200);
            }
            function change() {
                i++;
                btn.innerHTML = i;
            }
        }
    </script>
    <button id="btn"></button>
</body>

    定时器里的this是指向window的,因为定时器是window身上的一个方法,所以this指向window。可以用下面的方法进行this的传递。

<body>
    <script>
        window.onload = function () {
            var box = document.getElementById('btn');
            var i = 0;
            console.log(this);  //Window 
            box.onclick = function () {
                console.log(this); //btn 这里的this指向box
                var This = this;  //在这里把box传给了This,在这个函数内部可以访问到它
                setInterval(function () {
                    console.log(this);  //Window 
                    i++;
                    This.innerHTML = i;
                }, 200)
            }
        }
    </script>
    <button id="btn">0</button>
</body>

  三、清除定时器

   setInterval和setTimeout函数都是返回一个值,把这个值传入到对应的clearInterval和clearTimeout函数中,就可以取消对应的定时器了。可以声明一个变量把定时器的返回值都存到这个变量里,然后拿这个变量去清除定时器。

    清除重复执行定时器:clearInterval(定时器相对应的变量)

    清除延迟定时器:clearTimeout(定时器相对的变量)

    <script>
        window.onload = function () {
            var box = document.getElementById('btn');
            var n = 0;
            btn.onclick = function () {
                function add() {
                    n++;
                    btn.innerHTML=n;
                    if (n == 10) {
                        clearInterval(timer);
                    }
                }
                var timer = setInterval(add, 100);
            }
        }
    </script>
    <button id="btn">0</button>

  四、定时器的内部原理

    所有在浏览器中执行的js单线程异步事件都只有在它有空的时候才执行。计时器设定的延时是没有保证的。由于JavaScript每次只能执行一段代码,这就意味着,当一件异步事件(比如鼠标点击事件)触发的时候,这些事件的回调函数将排在执行队列的最后去等待执行。

    <script>
        btn.onclick = function () {
            setInterval(function () {
                console.log(1);
            }, 300)
        }
    </script>

    给btn按钮一个点击事件,事件处理程序设置了一个300ms后调用的定时器。点击按钮后,首先将onclick事件处理程序加入队列,这个程序执行后才设置定时器,再有300ms指定的代码才被添加到队列中等待执行。如果代码中的onclick事件处理程序执行了400ms,那定时器的代码至少要在定时器设置后的400ms后才会被执行。队列中所有的代码都要等到js进程空闲后才能执行,而不管它们是如何添加到队列中的。

  五、setImmediate

    setImmediate()方法用于中断长时间运行的操作并在浏览器完成其他操作(如事件和显示更新)后立即运行回调函数。这个方法是非标准的,只需要了解就可。

    语法:immediateID是这次setImmediate方法设置的唯一id,可以作为window.clearImmediate的参数。func是将要执行的回调函数。

    var immediateID=setImmediate(func,[param1,param2]);
    var immediateID=setImmediate(func);  

  六、requestAnimationFrame(H5新增)

    requestAnimationFrame的意思是请求动画帧。实现动画的方法比较的多,在js中可以用setTimeout来实现,css中可以用transition和animation来实现,html5中的canvas和requestAnimationFrame也可以实现。而编写动画循环的关键是要知道延迟时间多长合适。为了让不同的动画效果显示的平滑流畅且确保浏览器有能力渲染产生的变化。所以要有一个合适的循环间隔。

    普通电脑显示器的刷新频率是60Hz,相当于每秒钟重绘60次。大多数浏览器会对重绘操作加以限制不超过显示器的重绘频率。所以最平滑动画的循环间隔是1000ms/60,约为16.7ms。

    setTimeout它是通过设定间隔时间来不断改变图像位置达到动画效果,容易出现卡顿,抖动等现象。它的内部在运行机制上当setTimeout任务被放入异步队列中,只有主线程任务执行完成后才会执行队列中的任务,如果队列前面已经加入了其它任务,那动画代码要等前面的任务完成后再执行,实际执行时间比设定时间要晚。

    requestAnimationFrame它采用的是系统时间间隔,由系统决定回调函数的执行时机,60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会卡顿。改善视觉效果。

    特点:

    requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成了,并且重绘或回流的时间间隔紧紧跟随游览器的刷新频率。

    使用setTimeout实现动画,当页面被隐藏或是最小化时,setTimeout仍然在后台执行动画任务,这是浪费cpu资源的,而requestAnimationFrame当页面处于未激活的状态下,这个页面的屏幕刷新任务也被系统暂停,当页面激活时动画就从上次停留的地方继续执行,有效节省了cpu开销。

    在高频事件中,为了防止在一个刷新间隔内发生多次函数执行,使用requestAnimationFrame可保证每个刷新间隔内函数只被执行一次,这样可以更好的节省函数执行的开销,函数节流。

    使用:requestAnimationFrame的用法和setTimeout类似,只不过不需要设置时间间隔。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行。

    它有兼容性的问题,ie9浏览器不支持,需要降级对接口进行封装,优先使用高级特性,再根据浏览器不同情况进行回退,直到只能使用setTimeout。

    <script>
      window.onload=function(){
          var btn=document.getElementById('btn');
          var a=0;
          function add(){
              a++;
              btn.innerHTML=a;
              var timer=requestAnimationFrame(add);
              if(a>=100){
                  //注意:cancelAnimationFrame()一定要放在后面
                  cancelAnimationFrame(timer);
              }
          }
          add();
      }     
    </script>
 <button id="btn"></button>

    七、示例

  范例一:下拉广告

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        * { margin: 0; padding: 0; }
        #ad {background: url(images/big.jpg);}
    </style>  
</head>
<body>
    <script>
        window.onload = function () {
            var ad = document.getElementById('ad');
            var t1;
            var t2;  //声明变量存定时器
            var h = parseInt(getComputedStyle(ad).height);
            t1 = setInterval(function () {        
                h++;
                ad.style.height = h + 'px';     //把不断改变的值赋给ad

                //让其在250的高度时停止运动
                if (h == 250) {
                    clearInterval(t1);
                    //停止3s
                    t2 = setTimeout(function () {
                        //3秒到达后要重新的开一个定时器,以达到让收缩的效果 
                        t1 = setInterval(function () {
                            clearTimeout(t2);       
                            h--;
                            ad.style.height = h + 'px';
                            //要让div回到100的位置就停止
                            if (h == 100) {
                                clearInterval(t1);
                            }
                        }, 16)
                    }, 3000)
                }
            }, 16);
        }
    </script>
    <div id="ad"></div>
</body>
</html>

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!