为什么要用setTimeout来模拟setInterval
参考链接:https://blog.csdn.net/b954960630/article/details/82286486
setTimeout(fn,time): 等待time时间后执行fn
setInterval(fn,time) 每隔time时间执行fn
我们希望setInterval是每隔一段时间自动执行,但是实际应用中,setInterval并不会按照我们预想的那样,它通常存在如下两个缺点。
- 在执行的时候可能会跳过指定时间间隔
- 多个定时器函数会立刻执行
我们就实际场景来说一下这两个缺陷
时间间隔
首先明确一个概念,定时器的时间间隔指的是什么?
它不是指函数的执行时间,而是函数被推入到消息队列的时间。
也就是说每隔time时间,fn就会被放入消息队列中,而不是执行。另外何时执行取决于何时被主线程的事件循环取到
另外,如果前一个任务没有被执行,也就是还处于消息队列中怎么办呢? 浏览器规定**:只有当前消息队列中不存在该任务,才会将下一个任务推进去**
我们分析一下上面的情况,
- 隔了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)
优点:
- 在一个定时器执行完以前不会插入另一个定时器
- 确保了每个函数执行的等待时间间隔
上一篇: webAPI案例之十分钟搞懂js原生轮播
下一篇: 微信支付回调验证签名处理