【捣鼓】用setTimeout实现setInterval与clearInterval

试着分析试着解题部分是我边写边思考的过程,尝试每推导一步都问自己问题并设法回答。

如果觉得太罗嗦了可以直接跳到其他方法试着解题的末尾看代码。

如果有更好的办法或者文章中的办法有错误欢迎讨论与交流!

参考链接

setTimeout实现setInterval和clearInterval

利用setTimeout和clearTimeout封装setInterval和clearInterval

用setTimeout和clearTimeout简单实现setInterval与clearInterval

3. setTimeout模拟setInterval


试着分析

要用 setTimeout 实现 setInterval 就要知道这两者的定义是什么,有什么区别。

MDN:window.setTimeout

setTimeout() 方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。

MDN:window.setInterval

setInterval() 方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟。


对比二者在 MDN 文档给的定义,我们不难发现

二者的一个共同点:都是设置一个定时器,并在定时器到期后执行对应的函数或指定的一段代码;

二者的一个不同点:setTimeout 在执行完之后就停止了,setInterval 在执行完之后又开始了下一轮的计时。


这是我们从已有的条件获取到的信息,

现在再回头看看我们的目标是什么?

setTimeout 实现 setInterval


从我们获取到的信息出发,我们需要做什么才能达到目标?

或者换个角度,我们需要的达到的目标等价于什么,隐含着什么信息?

setTimeout 的功能来实现 setInterval 的功能,所以重点在于功能的实现,而二者的功能区别在前面已经知道了,故此时该做的就是保持共同点,消除不同点


那么,为了消除不同点,我们需要做什么呢?

需要在定时器到期且执行完函数之后,再一次开启定时器并执行上一次执行的函数,从函数的角度出发就是函数在执行完之后,每隔一段时间就又再次调用自身。


那么,怎么样才能每隔一段时间就调用自身呢?

回头看看条件, setTimeout 能够做到隔一段时间之后调用函数,接着,需要解决的问题就是调用自身了,怎么调用自身呢?这个不难,用递归呗。

(前面的东西可能看一眼题目就能直接想到了,不需要那么多介绍,但我想试着把我们一些默认的条件给点出来,从最开始的条件出发来思考,观察思考的过程)

function mySetInterval(fn, delay) {
   
    setTimeout(() => {
   
        fn();
        mySetInterval(fn,delay);
    }, delay);
}

这样一看,很轻松就实现了,那这个问题有什么难度,为什么还需要专门来总结?

看似是实现了 setInterval 的功能,但实际上 setInterval 还有一个返回值 intervalID

此返回值 intervalID 是一个非零数值,用来标识通过 setInterval() 创建的计时器,这个值可以用来作为 clearInterval() 的参数来清除对应的计时器 。

也就是说,我们实现的 mySetInterval 并不能完全的替代 setInterval ,只是实现了部分的功能。


那么,为什么我们会出现这个问题呢?从头看一下整理的思考过程,不难发现,问题是出在第一步,我们的对比不够完整,或者说用来比较的信息不够完整。


那么,我们接下来要做什么呢?

实现配套的 myClearInterval


这个 myClearInterval 需要有什么功能?

消除指定的 mySetInterval 计时器。


怎么实现这个功能呢?

第一个部分是指定计时器,第二部分是消除计时器。

要指定计时器就是需要给计时器加上指定的标记,以便获取。

消除计时器,可以使用 clearTimeout 来协助实现,也可以不使用这个,因为本质是获取对应的计时器标记,停止计时器的继续运行,前面 mySetInterval 计时器持续运行的原因是 不断地设置新的 setTimeout 计时器,那么,我们阻止这一行为即可。


试着解题

先看看指定计时器,也就是给计时器加上指定的标记。


那么从哪里获取标记呢?

回顾一下我们的条件,不难注意到 setTimeout 函数本身就会返回一个值,用来作为计时器的唯一标识,那我们直接用这个当作 mySetInterval 的返回值不就好了?

试试看。

function mySetInterval(fn, delay) {
   
    let timer = setTimeout(() => {
   
        fn();
        // 查看 timer 的变化
        console.log(timer); // 2 7 8 ... 19 20 ...
        mySetInterval(fn,delay);
    }, delay);
    return timer;
}

function myClearInterval(timer) {
   
    clearTimeout(timer);
}

/**
* 测试部分,后续方法默认采用如下代码的模板进行测试
*/

// 开启定时器
let t = mySetInterval(()=> {
   
    console.log('mySetInterval'
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值