写出输出结果:
const p1 = () => (new Promise((resolve, reject) => {
console.log(1);
let p2 = new Promise((resolve, reject) => {
console.log(2);
const timeOut1 = setTimeout(() => {
console.log(3);
resolve(4);
}, 0)
resolve(5);
});
resolve(6);
p2.then((arg) => {
console.log(arg);
});
}));
const timeOut2 = setTimeout(() => {
console.log(8);
const p3 = new Promise(reject => {
reject(9);
}).then(res => {
console.log(res)
})
}, 0)
p1().then((arg) => {
console.log(arg);
});
console.log(10);
答案:
1
2
10
5
6
8
9
3
第一步:浏览器开始将 script 标签包裹的所有代码看作宏任务执行,发现有普通的函数 p1,宏任务 timeOut2,使其进入宏任务队列,微任务 p1.then 进入微任务队列,普通的函数 p1 入栈,输出 1,普通函数 p2 入栈输出 2,有宏任务 timeOut1 入列,微任务 p2.then 入列。
第二步:宏任务执行完之后找微任务,队列是先进先出,then 按照 resolve 处理顺序,先执行的是 p2 中的 resovle 所以执行 p2.then,输出 5,再执行 p1 的 resolve,执行 p1.then,输出 6
第三步:微任务执行完后执行宏任务,由于两个 timeout 等待时间一样,按照队列顺序先执行 timeOut2 ,输出 8,p3.then 微任务入列,宏任务执行完毕后执行微任务 p3.then 输出 9。
第四步:执行 tineOut1,输出 3,由于 p2 的 promise 对象以及被执行过所以 4 不再执行
为了理解第二步为什么 p2.then 先于 p1.then 先执行,我们可以在打印上多加一点内容
var p1 = () => (new Promise((resolve, reject) => {
console.log(1);
let p2 = new Promise((resolve, reject) => {
console.log(2);
var timeOut1 = setTimeout(() => {
console.log(3);
}, 0)
resolve('5,resolve2');
});
resolve('6,resolve1');
p2.then((arg) => {
console.log(arg,'p2.then');
});
}));
var timeOut2 = setTimeout(() => {
console.log(8);
var p3 = new Promise(reject => {
reject(9);
}).then(res => {
console.log(res)
})
}, 0)
p1().then((arg) => {
console.log(arg,'p1.then');
});
console.log(10);
结果:
1
2
10
5,resolve2 p2.then
6,resolve1 p1.then
8
9
3
扩展:
如果两个timeout等待时间不一致结果也就不同了:
const p1 = () => (new Promise((resolve, reject) => {
console.log(1);
let p2 = new Promise((resolve, reject) => {
console.log(2);
const timeOut1 = setTimeout(() => {
console.log(3);
resolve(4);
}, 0)
resolve(5);
});
resolve(6);
p2.then((arg) => {
console.log(arg);
});
}));
const timeOut2 = setTimeout(() => {
console.log(8);
const p3 = new Promise(reject => {
reject(9);
}).then(res => {
console.log(res)
})
}, 1000)
p1().then((arg) => {
console.log(arg);
});
console.log(10);
结果:
1
2
10
5
6
3
8
9
第一步:浏览器开始将 script 标签包裹的所有代码看作宏任务执行,发现有普通的函数 p1,宏任务 timeOut2,使其进入宏任务队列,微任务 p1.then 进入微任务队列,普通的函数 p1 入栈,输出 1,普通函数 p2 入栈输出 2,有宏任务 timeOut1 入列,微任务 p2.then 入列。
第二步:宏任务执行完之后找微任务,队列是先进先出,then 按照 resolve 来定,先执行的是 p2 中的 resovle所以执行 p2.then,输出 5,再执行 p1的resolve,执行 p1.then,输出 6
第三步:微任务执行完后执行宏任务,由于 timeOut1 等待时间短,所以先执行,输出 3,由于 p2 的 promise 对象以及被执行过所以 4 不再执行;再执行 timeOut2 ,输出 8,p3.then 微任务入列
第四步:宏任务执行完毕后执行微任务 p3.then 输出 9