zoukankan      html  css  js  c++  java
  • setTimeout的妙用1——代替setInterval进行间歇调用

    【写在前面的胡言乱语】

      自从大三开始实习之后,就没有写博客了,虽然学了很多东西,但是如果没有进行总结和分享,学的东西就很容易忘记,而且不进行分享,就不会手动去敲代码,这样对知识的理解就不够透彻。

    现在毕业半年多了,最近学习了《JavaScript高级程序设计》这本书,受益匪浅,看了才知道虽然自己写了那么多JS,但是对JS的理解最多就只是中下水平。

    现在看第二遍,边看边敲代码,边分享,希望看到这篇文章的你,能有所收获。

     

    【这是正文】

      《JavaScript高级程序设计》这本书里面,介绍了很多关于setTimeout函数的神奇使用,今天来介绍下第一个——使用setTimeout代替setInterval进行间歇调用。

      书中是这么说的

    “在开发环境下,很少使用间歇调用(setInterval),原因是后一个间歇调用很可能在前一个间歇调用结束前启动”。

      这话怎么理解呢?

      首先我们来看一下一般情况下的setInterval函数的使用,以及如何使用setTimeout代替setInterval

      

    var executeTimes = 0;
    var intervalTime = 500;
    var intervalId = null;
    
    // 放开下面的注释运行setInterval的Demo
    intervalId = setInterval(intervalFun,intervalTime);
    // 放开下面的注释运行setTimeout的Demo
    // setTimeout(timeOutFun,intervalTime);
    
    function intervalFun(){
        executeTimes++;
        console.log("doIntervalFun——"+executeTimes);
        if(executeTimes==5){
            clearInterval(intervalId);
        }
    }
    
    function timeOutFun(){
        executeTimes++;
        console.log("doTimeOutFun——"+executeTimes);
        if(executeTimes<5){
            setTimeout(arguments.callee,intervalTime);
        }
    }

      代码比较简单,我们只是在setTimeout的方法里面又调用了一次setTimeout,就可以达到间歇调用的目的。

     

      重点来了,为什么作者建议我们使用setTimeout代替setInterval呢?setTimeout式的间歇调用和传统的setInterval间歇调用有什么区别呢?

     

      区别在于,setInterval间歇调用,是在前一个方法执行前,就开始计时,比如间歇时间是500ms,那么不管那时候前一个方法是否已经执行完毕,都会把后一个方法放入执行的序列中。这时候就会发生一个问题,假如前一个方法的执行时间超过500ms,加入是1000ms,那么就意味着,前一个方法执行结束后,后一个方法马上就会执行,因为此时间歇时间已经超过500ms了。

     

      书中没有给出代码证明这个结论,于是自己写了一段代码来验证。

     

    var executeTimes = 0;
    var intervalTime = 500;
    var intervalId = null;
    var oriTime = new Date().getTime();
    
    // 放开下面的注释运行setInterval的Demo
    // intervalId = setInterval(intervalFun,intervalTime);
    // 放开下面的注释运行setTimeout的Demo
    setTimeout(timeOutFun,intervalTime);
    
    function intervalFun(){
        executeTimes++;
        var nowExecuteTimes = executeTimes;
        var timeDiff = new Date().getTime() - oriTime;
        console.log("doIntervalFun——"+nowExecuteTimes+", after " + timeDiff + "ms");
        var delayParam = 0;
        sleep(1000);
        console.log("doIntervalFun——"+nowExecuteTimes+" finish !");
        if(executeTimes==5){
            clearInterval(intervalId);
        }
    }
    
    function timeOutFun(){
        executeTimes++;
        var nowExecuteTimes = executeTimes;
        var timeDiff = new Date().getTime() - oriTime;
        console.log("doTimeOutFun——"+nowExecuteTimes+", after " + timeDiff + "ms");
        var delayParam = 0;
        sleep(1000);
        console.log("doTimeOutFun——"+nowExecuteTimes+" finish !");
        if(executeTimes<5){
            setTimeout(arguments.callee,intervalTime);
        }
    }
    
    function sleep(sleepTime){
        var start=new Date().getTime();
        while(true){
            if(new Date().getTime()-start>sleepTime){
                break;    
            }
        }
    }

       (这里使用大牛提供的sleep函数来模拟函数运行的时间)

      执行setInterval的Demo方法,看控制台

     

      可以发现,fun2和fun1开始的间歇接近1000ms,刚好就是fun1的执行时间,也就意味着fun1执行完后fun2马上就执行了,和我们间歇调用的初衷背道而驰。

     

      我们注释掉setInterval的Demo方法,放开setTimeout的Demo方法,运行,查看控制台

     

      这下终于正常了,fun1和fun2相差了1500ms = 1000 + 500,fun2在fun1执行完的500ms后执行。

     

      不知道你有没有和我一样脑洞大开,反正我是感觉视野又开阔了一点,setTimeout的妙用还有很多,下次接着聊!

  • 相关阅读:
    mysql 约束条件介绍
    mysql 约束条件目录
    mysql 日期类型
    mysql float 浮点型
    mysql int 整数类型 解释显示宽度 和 存储宽度
    mysql 整数类型 数值类型 tinyint
    【洛谷P4096】Eden 的博弈树
    【GMOJ6824】英雄联盟
    【GMOJ6826】隔膜
    【POJ 2420】A Star not a Tree?
  • 原文地址:https://www.cnblogs.com/javdroider/p/6443985.html
Copyright © 2011-2022 走看看