为什么要使用setTimeout来实现SetInterval?
我们知道setInterval
以一定频率来执行一个函数,但是这样有一个问题,加入执行的这个函数相当耗时,超过了我们给定的周期时间,setInterval
还会按照约定的时间来执行下次任务吗?
答案是不会,setInterval
会等到当前的任务执行完成后,再立即执行下一次的任务,看个例子
setInterval(function interval() {
for(let i = 0; i < 10000000000; i++);
console.log('done')
}, 1000)
打印语句出现的时间会超过1s,那么第2s的打印操作也会随着被推迟。参考下图,setInterval每次的时间间隔是从任务开始时间开始算的,尽量与下一次任务的开始执行时间间隔和给定的时间间隔相同,一旦任务的执行时间超过了给定的时间间隔,那么下一次任务会被推迟,下次任务会在本次任务结束后来执行。
如何使用setTimeout来模拟setInterval?
借助与递归的思路,在上次任务结束后,立即安排下次任务的执行,这样保证上一个任务的结束时间到下一个任务的开始时间和给定时间是相等的
function setInterval2(fn, ms, ...args) {
let timeId = null
function tick() {
timeId = setTimeout(() => {
fn(...args)
tick()
}, ms)
}
fn(...args)
tick()
return () => clearTimeout(timeId)
}
function setInterval3(fn, ms, ...args) {
fn(...args)
let timeId = setTimeout(function tick() {
fn(...args)
timeId = setTimeout(tick, ms)
}, ms)
return () => clearTimeout(timeId) // 方便随时取消
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。