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的妙用还有很多,下次接着聊!

转载于:https://www.cnblogs.com/javdroider/p/6443985.html

### 什么是间歇函数 间歇函数通常指的是定时器功能中的 `setInterval` 方法,它是 JavaScript 中用于按照指定的时间间隔重复执行某段代码的一种机制。此方法会返回一个唯一的标识符(interval ID),可以通过 `clearInterval` 来停止其运行。 #### 定义 JavaScript 提供了一个内置全局方法 `setInterval()`,它可以用来定期调用某个函数或者执行一段代码。具体来说,`setInterval()` 接受两个主要参数:第一个是要执行的回调函数或要执行的代码字符串;第二个是以毫秒为单位的时间间隔[^5]。 ```javascript let intervalID = setInterval(function, delay[, argument1, argument2, ...]); ``` - **function**: 需要反复执行的函数。 - **delay**: 表示两次连续调用之间的延迟时间,以毫秒计。 - **argumentN**: 可选参数列表,这些参数会被传入每次调用函数中。 #### 用法实例 下面展示如何使用 `setInterval` 创建每两秒钟打印一次当前日期的功能: ```javascript // 每隔2秒打印一次当前时间 const id = setInterval(() => { console.log(new Date().toLocaleTimeString()); }, 2000); // 停止定时器 (假设我们想在十次之后结束) setTimeout(() => clearInterval(id), 20000); ``` 在这个例子中,首先设置了一种每隔两秒就向控制台输出本地时间的行为。接着为了防止无限循环下去,在二十秒后利用 `clearInterval` 终止了这一过程[^5]。 #### 结合闭包的应用场景 当涉及到更复杂的逻辑处理时,比如需要维护状态或者其他上下文信息,则可能需要用到闭包的概念来保存某些特定的状态值以便后续操作能够获取并更新它们。例如实现一个倒计时器就可以很好地体现这一点: ```javascript function countdown(secs){ let counter = secs; const timerId = setInterval(()=>{ console.log(`Time remaining: ${counter--} seconds`); if(counter < 0){ clearInterval(timerId); // 清除定时器 console.log("Countdown finished!"); } }, 1000); } countdown(5); ``` 这里定义了一个名为 `countdown` 的工厂函数,它接受初始秒数作为输入,并创建一个新的作用域链,其中包含了变量 `counter` 和 `timerId` 。每当定时器触发时,都会减少剩余时间直到达到零为止,此时清除定时器从而终止整个流程[^1]。 ### 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值