setInterval在执行完一次代码之后, 经过了那个固定的时间间隔, 它还会自动重复执行代码, 而setTimeout只执行一次那段代码。
- function mySetInterval(fn, wait) {
- let timer = null
- function interval() {
- fn()
- timer = setTimeout(todo, wait);
- }
- interval()
- }
带清除定时器版本
- function mySetInterval(fn, wait) {
- let timer = null
- function interval() {
- fn()
- timer = setTimeout(todo, wait);
- }
- interval()
- return () => clearTimeout(timer) //可以取消掉
- }
-
- let a = mySetInterval(() => {
- console.log(111);
- }, 1000)
-
- //可以清除掉定时器
- setTimeout(() => {
- a() //可以取消掉
- }, 1000);
- function mySetInterval(fn, t) {
- const timer = setInterval(() => {
- clearInterval(timer)
- fn()
- }, t)
- }
-
- mySetInterval(() => {
- console.log('hoho');
- }, 1000)
这里只做粗略回答:
为什么要用 setTimeout 模拟实现 setInterval?
定时器指定的时间间隔,表示的是何时将定时器的代码添加到消息队列,而不是何时执行代码。所以真正何时执行代码的时间是不能保证的,取决于何时被主线程的事件循环取到,并执行。
可以这么理解: 每个 setTimeout 产生的任务会直接 push 到任务队列中; 而 setInterval 在每次把任务 push 到任务队列前, 都要进行一下判断(看上次的任务是否仍在队列中, 如果有则不添加, 没有则添加)。
setInterval 的缺陷是什么 ?
1、推入任务队列后的时间不准确:在 setInterval 被推入任务队列时,如果在它前面有很多任务或者某个任务等待时间较长比如网络请求等,那么这个定时器的执行时间和我们预定它执行的时间可能并不一致。
2、函数操作耗时过长会导致不准确:假如定时器里面的代码需要进行大量的计算(耗费时间较长),或者是 DOM 操作。这样一来,花的时间就比较长,有可能前一次代码还没有执行完,后一次代码就被添加到队列了。也会导致定时器变得不准确,甚至出现同一时间执行两次的情况。