我们将包含then属性的对象称为thenable对象。
TC39规范
- If Type(resolution) is not Object, then Return FulfillPromise(promise, resolution).
- Let then be Get(resolution, “then”).
- If then is an abrupt completion, then Return RejectPromise(promise, then.[[Value]]).
- Let thenAction be then.[[Value]].
- If IsCallable(thenAction) is false, then Return FulfillPromise(promise, resolution).
- Perform EnqueueJob(“PromiseJobs”, PromiseResolveThenableJob, « promise, resolution, thenAction »).
让我们一步一步解释:
resolve 一个非对象元素
Promise.resolve('Hello').then(
value => console.log(`Resolution with: ${value}`)
);
// log: Resolution with: Hello
resolves 一个包含 abruptCompletion 的 then 对象
abruptCompletion 表示任何非正常的完成值。
const value = {};
Object.defineProperty(
value,
'then',
{ get() { throw new Error('no then!'); } }
);
Promise.resolve(value).catch(
e => console.log(`Error: ${e}`)
);
// log: Error: no then!
resolves 包含 then 且其属性不为函数的对象
Promise.resolve(
{ then: 42 }
).then(
value => console.log(`Resolution with: ${JSON.stringify(value)}`)
);
// log: Resolution with: {"then":42}
resolves 包含 then 且其属性为函数的对象
这部分是本文探讨的重点,也是递归promise链的基础。 当一个promise使用包含then方法的对象解析时,解析过程将then使用通常的promise参数调用resolve 和 reject。如果resolve没有被调用,promise将无法完成。
Promise.resolve(
{ then: (...args) => console.log(args) }
).then(value => console.log(`Resolution with: ${value}`));
// log: [fn, fn]
// | \--- reject
// resolve
// !!! No log of a resolution value
Promise.resolve(
{
then: (resolve) => {
console.log('Hello from then');
resolve(42);
}
}
).then(value => console.log(`Resolution with: ${value}`));
// log: Hello from then
// log: Resolution with: 42
动态导入
当您使用动态import函数加载JavaScript模块时,import遵循相同的过程,因为它返回一个promise。导入模块的结构值将是一个包含所有导出值和方法的对象。
// file.mjs
export function then (resolve) {
resolve('Not what you expect!');
}
export function getValue () {
return 42;
}
// index.mjs
import('./file.mjs').then(
resolvedModule => console.log(resolvedModule)
);
// log: Not what you expect
##内存泄露的风险 参考co库的这个 issue https://github.com/tj/co/issues/180
原文地址:https://www.stefanjudis.com/today-i-learned/promise-resolution-with-objects-including-a-then-property/