第一段代码
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一个then");
return new Promise((resolve, reject) => {
console.log("内部promise");
resolve();
})
.then(() => {
console.log("内部第一个then");
})
.then(() => {
console.log("内部第二个then");
});
})
.then(() => {
console.log("外部第二个then");
});
output:
外部promise
外部第一个then
内部promise
内部第一个then
内部第二个then
外部第二个then
这里需要注意的是,外部第一个then后面是一个return语句,外部第二个then是依赖于这个return的结果的,所以第二个then是会等这个return 后面执行完出结果才会执行;所以最后才打印外部第二个then
第二段代码
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一个then");
new Promise((resolve, reject) => {
console.log("内部promise");
resolve();
})
.then(() => {
console.log("内部第一个then");
})
.then(() => {
console.log("内部第二个then");
});
})
.then(() => {
console.log("外部第二个then");
});
output:
外部promise
外部第一个then
内部promise
内部第一个then
外部第二个then
内部第二个then
这里可能让人很不解的地方在于,为什么 内部第一个then会在外部第二个then前面?
我们都知道,事件机制是“先注册先执行”,即数据结构中的队列模式。所以要解释这个问题需要看看谁先注册的。
外部的第二个then的注册,需要等待外部第一个then内的同步代码执行完成。
如图所示,代码到resolve这都是同步的(包括resolve方法也是同步的);重点来了:resolve执行完成,代表此时的改promise状态已经扭转,之后开始内部的第一个.then的微任务注册,此时同步执行完成,外部第二个then才注册;所以内部第一个then早于外部第二个then注册;所以内部then第一个then先执行(此时也完成了内部第二个then的注册),外部第二个then紧接着执行,最后执行内部第二个then.
第三段代码
new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
.then(() => {
console.log("外部第一个then");
let p = new Promise((resolve, reject) => {
console.log("内部promise");
resolve();
})
p.then(() => {
console.log("内部第一个then");
})
p.then(() => {
console.log("内部第二个then");
});
})
.then(() => {
console.log("外部第二个then");
});
output:
外部promise
外部第一个then
内部promise
内部第一个then
内部第二个then
外部第二个then
这段代码的差异,就是内部的Promise的代码不再是链式调用。
两个p.then是同步代码,所以先注册 内部第一个then、紧接着 注册 内部第二个 then;最后同步代码执行完 注册 外部第二个then,此时任务队列中有三个任务,再按照先进先出的原则依次执行这三个任务。
第四段代码
let p = new Promise((resolve, reject) => {
console.log("外部promise");
resolve();
})
p.then(() => {
console.log("外部第一个then");
new Promise((resolve, reject) => {
console.log("内部promise");
resolve();
})
.then(() => {
console.log("内部第一个then");
})
.then(() => {
console.log("内部第二个then");
});
})
p.then(() => {
console.log("外部第二个then");
});
output:
外部promise
外部第一个then
内部promise
外部第二个then
内部第一个then
内部第二个then
这块同理,两个p.then是同步注册的,外部第一个then内执行到resolve方法时才开始注册内部第一个then,所以外部第二个then先打印,再打印内部第一个then
总结
- promise的链式调用两个then,第二个then的注册需要等第一个then内的同步代码执行完成(注意:resolve方法也算同步方法,只是后面的then是异步的)。并且微任务队列是先注册先执行。
- 如果第一个then内有return,第二个then会等return 语句执行完才开始注册