“时光穿梭:setTimeout演绎setInterval的精准节奏”

112 阅读2分钟

计时器在开发过程中有着

setTimeout

setTimeout是异步执行的计时器,在我们的开发过程中经常需要用到

特性

  • 异步执行:不会阻塞主线程的执行。
  • 延迟执行:在指定的时间(以毫秒为单位)后执行回调函数。

image.png
以上相较于主线程延迟1000ms执行console.log"hello,world",计时器返回值由timeout接收其值为一个id

setInterval

setInterval 用于每隔一定的时间(以毫秒为单位)重复执行一次回调函数。它返回一个唯一的

特性

  • 重复执行:每隔指定的时间执行一次回调函数。
  • 可清除:通过返回的 ID 可以停止定时器的执行。
    具体操作,我们可以通过定义一个interval来接收setInterval()返回的id,然后添加一个按钮,给按钮添加一个事件监听点击按钮执行clearInterval(interval)来清除定时器。

image.png

如何用setTimeout 来实现setInterval呢?

  • 定义一个名为 customSetInterval 的函数,它接受两个参数:fn(要执行的函数)和 time(时间间隔,以毫秒为单位)
  • 声明一个变量 intervalId,初始值为 null。这个变量将用于存储 setTimeout 返回的定时器 ID。
  • 定义一个名为 loop 的内部函数,这个函数将用于递归地调用 setTimeout。

image.png

  • 接下来我们只需要执行loop()函数启动定时器,就能实现每隔time(ms)执行一次fn()函数
  • 最后返回一个清除函数来清除定时器

image.png

注意:由于 intervalId 在每次 setTimeout 调用后都会被更新,因此 return () => clearTimeout(intervalId); 返回的函数实际上只能清除最后一次的 setTimeout 调用,而不是整个循环。这意味着,一旦循环开始,通过这个函数来停止整个循环是不可行的,因为它只能影响到最后一次的定时器。

如果要完全停止循环需要在loop()函数中设置一个控制逻辑来结束递归,具体操作

ending

通过这种方式,我们可以使用 setTimeout 来模拟 setInterval 的行为,同时保持对执行间隔的精确控制。