js执行顺序
多数情况,被问到的是包含直接运行,setTimeout和Promise这三个的顺序先后,就以一段简单的代码来作为例子说明一下:
console.log('任务执行开始')
setTimeout(()=>{
console.log('从计时器开始执行')
},0)
new Promise((resolve, reject) => {
console.log('promise开始执行')
resolve()
}).then(() => {
console.log('promise结束执行')
})
console.log('任务执行完毕')
这段执行任务的输出并非如同打印的文本的那样直接,而是一系列的任务先后,其输出结果如下:
- 最开始,进入此段代码时,先检测一下是否存在微任务,如果有则会先去执行微任务,故而js运行时,微任务总是先于宏任务执行。然后在检测到不存在微任务的时候,运行到第一个
console.log('任务执行开始')
的时候,直接执行,输出“任务执行开始”。 - 接下来遇到的是
setTimeout()
函数,这时候并不会立即执行,虽然他也是宏任务,但傲娇的js会把他放到下一次宏任务去执行,即本次无输出。 - 紧接着遇到Promise,这时候会进入Promise函数中,执行里面的代码,也就是
console.log('promise开始执行')
,然后遇到了正在焦急等待的回调函数,只不过js作为一个单线程的细胞生物,还是把它放到了微任务的任务队列中,这时候只输出了“promise开始执行”。 - 然后到了最后,遇到了
console.log('任务执行完毕')
,也是直接执行并输出“任务执行完毕” - 此时输出的有三个:
【1】任务执行开始
【2】promise开始执行
【3】任务执行完毕 - 当js的宏任务执行完成之后,才开始执行微任务,这时候进入到任务队列中,依次执行,注意的是刚刚的
setTimeout()
并不是微任务,所以和目前微任务不在一个任务队列中。 - 往下走,遇到之前的Promise回调函数,此时不再拒绝他的js会立即执行此任务,输出“promise结束执行”。
- 然后当所有的执行完毕之后,js进入下一段艰难的任务,执行了之前放到本次执行的
setTimeout()
,然后如此往复。 - 所以最后的结果,便如上图所示。