开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
- 请讲一讲setTimeout() 和 setInterval() ?
- 那不是张口就来。
setTimeout表示推迟一段时间延迟执行。setInterval则表示间隔一段时间重复执行。 - 那你能说说
setInterval的缺点吗?你能说说如何使用setTimeout实现setInterval吗?你知道为什么要用setTimeout实现setInterval吗?
我突然一脸懵逼。。。。
那我们今天就来深入研究一下setTimeout() 和 setInterval()。
setInterval的缺点
其实是因为javascript是单线程环境,也就是说定时器仅仅是计划在某个时间段执行,但实际并不能保证执行的时机。
我们有如下需求:假定每隔100ms执行某段代码。
那么我们针对这一需求,肯定会优先选择setInterval实现。
考虑极端情况,假定定时器的代码中需要进行大量的计算,会花费比较长的时间,那么就存在前一次代码还没有执行完成,后一次代码就被添加到队列里了。
如下图所示,假设时间间隔为100ms,需要执行代码的时间为300ms,如图所示:
简单分析一下:100ms时,队列空闲,代码进入队列,定时器内的代码会被执行。200ms时,第一次定时器中的代码仍在执行,第二次定时器的代码被推入事件队列,等待执行。300ms时,因为第二次的定时器的代码仍在队列中等待,因此这一次代码不会被推入队列中。400ms时,第一次定时器的代码执行完成,队列空闲,第二次定时器的代码开始执行。
因此我们可以看到setIntreval 实现不了需求,并没有达到定时器的效果。可以总结为:1.使用setInterval时,某些间隔会被跳过;即使setInterval调用的方法报错了,他仍然会继续执行。
2.无视网络延迟,可能多个定时器会连续执行。
因此可以这么理解:每个setTimeout产生的任务会直接push到任务队列中;而setInterval在每次把任务push到任务队列前,都要进行一下判断(看上次的任务是否仍在队列中)。
因此我们一般用 setTimeout 模拟 setInterval,来规避掉上面的缺点。
用 setTimeout 模拟 setInterval
const repeat = (func, ms) => {
setTimeout(() => {
func()
repeat(func, ms)
}, ms)
}