如果使用Promise p(或Thenable)的值解析Promise q,它实际上将成为Promise的副本q.如果q已解决,p将以相同的值解析.
Promise.resolve(Promise.resolve("hello"));
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
Run Code Online (Sandbox Code Playgroud)
如果q被拒绝,p将被拒绝具有相同的值.
Promise.resolve(Promise.reject(new Error("goodbye")));
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Error: goodbye}
Run Code Online (Sandbox Code Playgroud)
Promise p通过Promise解决/拒绝的事实q,而不是直接与相应的价值相关,这与最终结果无关.中间Promise作为解决过程的一部分被消费,并且对消费者不可见.
如果q是永不解决或拒绝,p也将永远保持待定.
Promise.resolve(new Promise(() => null)); // perpetually-pending promise
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Run Code Online (Sandbox Code Playgroud)
这些案例众所周知,但我从未见过如果Promise被另一个Promise值拒绝(而不是解决)会发生什么.拒绝过程是否也消耗中间承诺,还是通过完整传递?
如果它确实消耗它们,那它是如何工作的?
小智 7
让我们看看如果我们拒绝承诺p已解决的Promise 会发生什么q:
Promise.reject(Promise.resolve("hello"));
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Promise {
[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
Run Code Online (Sandbox Code Playgroud)
或者更明确地说:
const q = Promise.resolve("hello");
const p = Promise.reject(q);
p.then(null, x => console.log("Rejection value:", x));
Run Code Online (Sandbox Code Playgroud)
Rejection value: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "hello"}
Run Code Online (Sandbox Code Playgroud)
Promise q,拒绝价值,永远不会被打开! p拒绝处理程序是用Promise q本身调用的,而不是它包含的值.
这也意味着p拒绝处理程序q在运行之前不需要等待解析.即使q永远不会解决,p仍然可以调用拒绝处理程序.
Promise.reject(new Promise(() => null)); // Reject with perpetually-pending Promise
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Promise {
[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Run Code Online (Sandbox Code Playgroud)
最后,如果我们p使用另一个被拒绝的Promise 拒绝Promise,那么让我们确认一下这种行为q:
Promise.reject(Promise.reject(new Error("goodbye")));
Run Code Online (Sandbox Code Playgroud)
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Promise}
Uncaught (in promise) Error: goodbye(…)(anonymous function)
Uncaught (in promise) Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: Error: goodbye}
Run Code Online (Sandbox Code Playgroud)
我们再次看到q它没有被解开,并且p将拒绝处理拒绝处理程序q,而不是q被拒绝的值.
所以,Jeremy的回答解释了会发生什么:
const p = Promise.reject(Promise.resolve(3));
Run Code Online (Sandbox Code Playgroud)
p被拒绝的承诺,拒绝价值Promise为3.
我们被教导相信承诺永远不会兑现承诺!嗯,这是一个特例.在这里,我们拒绝承诺与另一个承诺相矛盾的承诺then.
容易运动.让我们首先得到一些术语.
承诺开始为待定,它可以成为:
到目前为止一切顺利,但让我们考虑另外两个术语:
唷.现在已经不在了:
什么Promise.resolve是创造一个解决另一个价值的承诺.如果该值是一个它跟踪它的一个承诺 - 否则它会立即与传入的值结算.如果你return来自函数中的某个then或await某个东西,也会发生这种情况async.
什么Promise.reject是创建一个被另一个值拒绝的承诺.它没有机会遵循另一个承诺,因为它会立即被拒绝的结果创建.
此行为在reject和中指定resolve.特别是 - 我们正在创建一个承诺能力并且resolve很特别 - 即看看"Promise Resolve Functions".
好吧,让我们考虑一下替代方案.我们要resolve模仿从返回then或正在等待的async功能和reject模仿throwING在一个then或一个async功能.
const p = Promise.resolve().then(() => {
throw Promise.reject(5);
});
Run Code Online (Sandbox Code Playgroud)
更清楚地看到解决p5对没有意义!我们将承诺标记为正确完成,但显然没有正确完成.
同理:
async function foo(){throw Promise.resolve(5); } foo(); //没人会指望foo解决
这意味着我们将失去有关我们正在处理哪些拒绝的信息.唯一的选择是拒绝一个Promise对象.
没有永不.你永远不应该throw承诺,你应该总是拒绝与Errors.