欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

为什么要用setTimeout来模拟setInterval

程序员文章站 2022-03-30 11:52:14
...

参考链接:https://blog.csdn.net/b954960630/article/details/82286486

setTimeout(fn,time): 等待time时间后执行fn
setInterval(fn,time) 每隔time时间执行fn
我们希望setInterval是每隔一段时间自动执行,但是实际应用中,setInterval并不会按照我们预想的那样,它通常存在如下两个缺点。

  1. 在执行的时候可能会跳过指定时间间隔
  2. 多个定时器函数会立刻执行

我们就实际场景来说一下这两个缺陷

时间间隔

首先明确一个概念,定时器的时间间隔指的是什么?
它不是指函数的执行时间,而是函数被推入到消息队列的时间
也就是说每隔time时间,fn就会被放入消息队列中,而不是执行。另外何时执行取决于何时被主线程的事件循环取到

另外,如果前一个任务没有被执行,也就是还处于消息队列中怎么办呢? 浏览器规定**:只有当前消息队列中不存在该任务,才会将下一个任务推进去**

为什么要用setTimeout来模拟setInterval
我们分析一下上面的情况,

  • 隔了100ms之后,将t1推进去,因为js栈中主进程还没有执行完,所以t1这时候等待执行,
  • 又过了100ms,t1已经执行,t2被压入队列中
  • 又过了100ms,t1还没执行完,t2还存在在消息队列中,所以t3根据规定不能被压入队列中

所以这时候你就会发现,t1 、 t2是连续执行的,他们之间没有时间间隔,满足不了我们的需求。

而我们可以用setTimeout模拟来弥补这两个缺陷。

setTimeout 模拟 setInterval

可以这么理解:
setTimeout执行后会立刻将fn放入到消息队列中,而setInterval每次在放入之前都会判断消息队列中存不存在上一个任务。

setTimeout的执行机制,也就是浏览器的事件循环机制,setTimeout是一个宏任务,当js栈空了,就会依次执行宏任务。
详细请看这一篇博客:
前端不可不知的 Event loop

代码实现:

setTimeout(function a(){
	//.....
	setTimeout(a,time)

},time)

优点:

  1. 在一个定时器执行完以前不会插入另一个定时器
  2. 确保了每个函数执行的等待时间间隔
相关标签: 前端知识总结