JavaScript在浏览器中是单线程执行的,但允许使用定时器指定在某个时间之后或每隔一段时间就执行相应的代码。setTimeout()用于指定在一定时间后执行某些代码,而setInterval()用于指定每隔一段时间执行某些代码。
定时器方法通常接收两个参数:第一个参数通常是一个函数,第二个参数是要等待的毫秒数(注意不是要执行代码的确切时间)。因为JavaScript是单线程的,所以每次只能执行一段代码。为了调度不同代码的执行,JavaScript维护了一个任务队列。其中的任务会按照添加到队列的先后顺序执行。
setTimeout()的第二个参数只是告诉JavaScript引擎在指定的毫秒数过后把任务添加到这个队列。如果队列是空的,则会立即执行该代码。如果队列不是空的,则代码必须等待前面的任务执行完才能执行。
setInterval()的第二个参数指的是向队列添加新任务之前等待的时间。浏览器不关心这个任务什么时候执行或者执行要花多长时间,只要是达到这个间隔时间他就会像向队列添加新任务。
简单总结下就是第二个参数并不是何时执行这里的回调函数,而是何时会把回调函数加到任务队列。即便是把回调函数添加到浏览器的任务队列,也不能保证添加到队列就会立即运行,如果队列前面还有其他任务,那么就要等这些任务执行完再执行。
通常设置循环任务的推荐做法是使用setTimeout(), 因为setInterval()可能会产生任务堆积,所以很少会在生产环境下使用。
let num = 0, max = 10, intervalId = null;
function incrementNumber() {
num++;
if (num >= max) {
clearInterval(intervalId);
console.log('Done');
}
}
intervalId = setInterval(incrementNumber, 500);
let num = 0, max = 10;
function incrementNumber() {
num++;
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
console.log('Done');
}
}
setTimeout(incrementNumber, 500);