如果Promise的resolver函数被调用时传入了一个 thenable 对象(包括另一个 Promise
实例),则该 thenable 对象的 then
方法将被保存并在未来被调用(它总是异步调用)
这意味着像下面这样的代码:
new Promise((resolve, reject) => {
resolve(thenable);
});
大致相当于:
new Promise((resolve, reject) => {
try {
thenable.then(
(value) => resolve(value),
(reason) => reject(reason),
);
} catch (e) {
reject(e);
}
});
但是在 resolve(thenable)
的情况中,有如下区别:
resolve
函数是同步调用的,因此再次调用resolve
或reject
函数没有任何影响,即使通过anotherPromise.then()
绑定的处理程序尚未被调用。then
方法是异步调用的,因此如果传入 thenable 对象,则该Promise
对象不会被立即解决。
因此实际等价的代码如下:
new Promise((resolve, reject) => {
// 或者使用Promise.resolve().then(()=>{...})注册异步任务
queueMicrotask(()=>{
try {
thenable.then(
(value) => resolve(value),
(reason) => reject(reason),
);
} catch (e) {
reject(e);
}
})
});
示例:
const p = new Promise((r) => r()).then(() => console.log(3));
new Promise((r) => {
console.log(1);
r(p); // 等价于 queueMicrotask(()=>p.then(r))
}).then(() => console.log(6));
new Promise((r) => {
console.log(2);
r();
})
.then(() => console.log(4))
.then(() => console.log(5))
.then(() => console.log(7));
// 输出结果 1234567
const p = new Promise((r) => r())
.then(() => console.log(3))
.then(() => {
console.log(5);
return 8;
});
new Promise((r) => {
console.log(1);
r(p); // 等价于 queueMicrotask(()=>p.then(r))
}).then((a) => console.log(a));
new Promise((r) => {
console.log(2);
r();
})
.then(() => console.log(4))
.then(() => console.log(6))
.then(() => console.log(7))
.then(() => console.log(9))
.then(() => console.log(10));
// 输出结果 1 2 3 4 5 6 7 8 9 10