请写出下面代码的打印结果
console.log( 'script start' );
function run() {
setTimeout(() => {
console.log( 'timeout 1' );
}, 0);
new Promise((resolve, reject) => {
console.log( 'promise 1' );
resolve(1);
}).then(() => {
console.log( 'promise 1 then' );
})
setTimeout(() => {
console.log( 'timeout 2' );
}, 0);
}
run();
setTimeout(() => {
console.log( 'timeout 3' );
new Promise((resolve, reject) => {
console.log( 'promise 2' );
resolve(2);
}).then(() => {
console.log( 'promise 2 then' );
})
}, 0);
console.log( 'script end' );
注意:一般情况下,js会先把同步代码执行完,然后再去执行异步代码
- 第一行 console.log 为同步代码,立即执行所以先打印
script start
- 后面是一个函数声明,先跳过
- run() 函数执行
- 首先遇到一个定时器,不属于同步代码,所以会把他先放到宏任务队列中
此时的宏任务队列
console.log( 'timeout 1' );
- 遇到了一个 Promise,new Promise会立即执行的,属于同步代码,打印出
promise 1
,then里面的代码属于异步代码,但是它属于一个微任务,所以先放到微任务队列中
此时的微任务队列
console.log( 'promise 1 then' );
- 接着遇到了一个定时器,会把他放到宏任务队列中
此时的宏任务队列
console.log( 'timeout 1' );
console.log( 'timeout 2' );
- 继续执行 run() 后面的代码,遇到一个定时器,会把他继续放到宏任务队列中
此时的宏任务队列
console.log( 'timeout 1' );
console.log( 'timeout 2' );
console.log( 'timeout 3' );
new Promise((resolve, reject) => {
console.log( 'promise 2' );
resolve(2);
}).then(() => {
console.log( 'promise 2 then' );
})
- 接着执行定时器后面的 console.log,同步代码,立即执行,打印出
script end
- 此时这一整块代码的同步代码都执行完毕了,现在js会去查看微任务队列中有没有未执行完的代码,发现有,立即执行
此时的微任务队列
console.log( 'promise 1 then' );
打印promise 1 then
,此时微任务队列已经全部执行完成了
- 接着该去查找宏任务队列了,
此时的宏任务队列
console.log( 'timeout 1' );
console.log( 'timeout 2' );
console.log( 'timeout 3' );
new Promise((resolve, reject) => {
console.log( 'promise 2' );
resolve(2);
}).then(() => {
console.log( 'promise 2 then' );
})
发现宏任务队列中也有未执行完的代码,所以从上到下依次执行,前三个任务都属于同步代码,相信大家没什么疑问,连续打印出timeout 1
,timeout 2
,timeout 3
- 接着遇到了 Promise,前面已经说过了,Promise 内部代码属于同步代码,立即执行,打印出
promise 2
,then 里面的代码属于异步代码,放到微任务队列中
微任务队列
console.log( 'promise 2 then' );
- 此时,宏任务队列中的任务已经全部执行完毕,接着查看微任务队列,发现有未执行的代码,继续执行,打印
promise 2 then
- 接着再查看宏任务队列是否还有未执行完成的任务,没有了,全部代码执行完成,停止
最终的打印结果为
script start
promise 1
script end
promise 1 then
timeout 1
timeout 2
timeout 3
promise 2
promise 2 then