zoukankan      html  css  js  c++  java
  • setInterval和setTimeout的缺陷和优势分析

    先把问题摆出来:
    使用定时器的setInterval()方法会出现程序并不是按照我们设定的精确时间而调用的问题!

    定时器:

    在JavaScript中经常会使用定时器来进行延时或者是重复调用的操作;定时器有两个方法:
    1:setInterval(参数1,参数2);
    参数1:要执行的代码,可以为function();
    参数2:间隔时间 单位ms;
    执行无限次直到取消定时器。

    2:setTimeout(参数1,参数2);
    参数1:要执行的代码,可以为function();
    参数2:延迟时间 单位ms;
    执行一次。

    注意区分:setInterval()的参数2是间隔时间,setTimeout()的参数2是延迟时间;
    这一段将是接下来进行二者详细区分的重要根据;

    一:setInterval() 辉煌下隐藏的破败##

    实例1

    var num = 0;
        var test1 =  setInterval(function (){
            num++;
            var data = new Date();
            var str = data.getHours() + ":" + data.getMinutes() + ":" + data.getSeconds() + ":" + data.getMilliseconds();
            console.log(str);
            if (num > 5) {
                clearInterval(test1);
            }
        },1000);

    1:代码;程序设置定时器每1秒执行一次,当执行次数为六次时消掉计数器;
    2:从运行结果上来看,在精确到毫秒之后就有些许的波动;
    实例2

    var num2 = 0;
        var test2 = setInterval(function(){
            num2++;
            for(var i = 0;i < 500000;i++){
                var div = document.createElement("div");
                var container = document.getElementById("d1");
                container.appendChild(div);
            }
            var data = new Date();
            var str = data.getHours() + ":" + data.getMinutes() + ":" + data.getSeconds() + ":" + data.getMilliseconds();
            console.log(str);
            if(num2 > 5){
                clearInterval(test2);
            }
        },1000);

    1:代码描述:定时器中有一个50万次的循环,创建和追加div元素这个操作是非常耗费性能的,运行一次我这破机子瞬间不好了;执行完一次for循环之后就输出一次当前的时间,运行六次就消除定时器。
    2:执行结果:如图所示每一次执行定时器的操作的时间相差分别是7,9,9,12,13秒,
    哎!!定义的不是每一秒执行一次吗?为什么出现相差 这么多秒!!!!???
    此时请出在开头亮出来的问题:
    setInterval()方法会出现程序并不是按照我们设定的精确时间而调用的问题!!!;
    这是为什么?我设置了程序调用时间为什么又不按照我说的办了??

    简单地画了个图,描述一下程序的执行时间为什么会产生错乱。
    图一:
    这里写图片描述

    这张图描述的是当A <= B时的调用状况。此时程序每一次的执行根本就不会影响到定时器设置的间隔调用;所以此时会产生实例1中输出的时间是严格按照我们所设定的精确时间进行调用;

    图二:
    这里写图片描述
    曾经我以为使用定时器的函数,只要到达了设置的间隔时间,即使他没有执行完也会被定时器强行的从栈中扯出来从头开始执行,这样从头到尾就没有一次是完整的执行出来的;这TM怎么可能!!!!实例2就已经实力打脸了!

    真正的执行是这样的---------图三:

    你看,这每一个圆圈代表每一次的程序执行时间A,底下那各自连接不上的憋屈红线就是定时器设置的间隔时间B,和图二是截然不同的,只有在函数每一次执行完之后才会调用定时器,继续重新进行调用;卧槽?这是为啥?这才是导致开头问题的原因!!!
    所以我把这一节称之为辉煌下的破败

    重点原理:

    JavaScript是运行在单线程的环境中的,所以这就意味着定时器就成了要执行的计划!而不是必须要执行的铁律! 为啥呢? 当函数开始执行时在栈中创建出来一个栈帧,这个栈帧的执行是需要时间的,假设有3秒,在这三秒内,JavaScript的单线程特点就会确保在这3秒内全力的专一的去解决掉这个栈帧(函数)。所以在这个函数运行的时候定时器是没有能力终止他的运行的,因此当函数的运行时间大于间隔时间时,间隔时间1秒到了,但是程序还有2秒没有执行完,那你也给我老老实实的等着函数执行完!!!!

    二:setTimeout() 平凡的力量##

    奇坑无比的setInterval()有着看似无法解决的弊端;
    据说有一种解决思路就是将间隔时间设置的大点,远大于函数执行的时间。。。定时器说了,老子管不了你还不能装看不见吗? 眼不见心不烦。。。
    乍一看,确实有道理,但是这也不大合适,就像前面实例2中,每一次执行同一个函数的执行时间都是有些区别的。你该怎么去设置这个间隔时间呢?设置的大点?从实际上出发是不合适,因此果断抛弃。

    在setTimeout()中,他的参数2代表的是延迟时间,他是先延迟后执行,setInterval()是先执行,后使用时间间隔;无限次执行;

    原理图:
    这里写图片描述
    如图先有一段延迟时间,之后再执行函数方法;可以看到参数2 的延迟时间对函数的执行是毫无影响的;此时如果把setTimeout放到循环体中,那么是不是代表这就是一个秩序井然的程序。既可以达到setInterval的循环执行的效果,又解决了setInterval的时间不精确的问题;

    var i=0;
        function show() {
            console.log(i);
            i++;
            if(i<5){
                setTimeout(show,1000);
            }
        }
        show();

    停止超时调用方法:

    这是一段骚气的代码,如此造成循环每隔1秒就输出i;


    总结
    1:setInterval的参数2是间隔时间;
    2:setTimeout的参数2是延迟时间;
    3:setInterval受单线程影响出现时间不精确现象;
    4:使用循环+setTimeout可以完成循环执行,并且弥补了setInterval的不足;

  • 相关阅读:
    Crystal Reports基础知识
    Dashboard与中国式报表的区别以及常见的Dashboard控件
    函数总结
    SQL Server 索引使用入门
    Linux+C 开发基础
    vi 开发环境~~转载
    linux mysql 基础操作使用
    sourceinsight 快捷键 转帖
    vi 利器
    fedora 7 英文环境 的汉字显示
  • 原文地址:https://www.cnblogs.com/BluceLee/p/13749706.html
Copyright © 2011-2022 走看看