虽然setInterval是前端会经常使用的一个函数,它的作用是循环执行任务。但是很多人在使用这个函数时还是会遇到很多问题。那么就来大致了解一下这个函数的运行机制。
setInterval的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。这意味着,setTimeout指定的代码,必须等到本次执行的所有代码都执行完,才会执行。·
每一轮Event Loop时,都会将“任务队列”中需要执行的任务,一次执行完。setTimeout会把任务添加到“任务队列”的尾部。也就是说要他要等到当前脚本的所有同步任务执行完,然后再等到本次Event Loop的“任务队列”的所有任务执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setInterval指定的任务,一定会按照预定时间执行。
例:
setInterval(function(){
console.log(2);
},1000);
(function (){
sleeping(3000);
})();
上面的第一行语句要求每隔1000毫秒,就输出一个2。但是,第二行语句需要3000毫秒才能完成,请问会发生什么结果?·
结果就是等到第二行语句运行完成以后,立刻连续输出三个2,然后开始每隔1000毫秒,输出一个2。也就是说,setIntervel具有累积效应,如果某个操作特别耗时,超过了setInterval的时间间隔,排在后面的操作会被累积起来,然后在很短的时间内连续触发,这可能或造成性能问题
再举一个也是很多人遇到的问题:为什么我的setInterval中的任务执行了一次就不执行了?
那么他们是怎么写的呢?相信出现这个问题的同学都是这样写的:
var fun = function(){
alert(1)
}
setInterval(fun(),1000)
要解决这个问题,需要了解setInterval的传参。
如图所示,传入setInterval中的第一个参数,需要是函数体或者可执行代码串(可以是字符串)
那么上面代码中有什么问题呢。问题就是setInterval中的函数体,不是fun而是fun执行后的返回,也就是undefined,那么现在来看这段代码就很明显了:先执行一次fun(),然后循环执行undefined。
所以正确的应该是:
var fun = function(){
alert(1)
}
setInterval(fun,1000)
上面的代码,会在当前任务队列中没有耗时代码的情况下,应该是在1s之后执行alert。
但是如果想要立即执行该函数,然后循环执行呢?
当然可以手动执行,然后调用setInterval
或者:
var fun = function haha(){
alert(1)
return haha
}
setInterval(fun(),1000)
来实现。