如果我拒绝承诺具有另一个Promise值,会发生什么?

5 javascript promise

如果使用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被拒绝的值.

  • @ guest271314这个答案显示了问题的答案. (3认同)
  • 也许@ guest271314.如果您无法理解 - 请提出另一个问题来解释这个问题.(我们需要更深入) (3认同)

Ben*_*aum 5

所以,Jeremy的回答解释了会发生什么:

const p = Promise.reject(Promise.resolve(3)); 
Run Code Online (Sandbox Code Playgroud)

p被拒绝的承诺,拒绝价值Promise为3.

我们被教导相信承诺永远不会兑现承诺!嗯,这是一个特例.在这里,我们拒绝承诺与另一个承诺相矛盾的承诺then.

但为什么?!?

容易运动.让我们首先得到一些术语.

承诺开始为待定,它可以成为:

  • 履行 - 用一个值标记完成.
  • 拒绝 - 标记失败的原因.

到目前为止一切顺利,但让我们考虑另外两个术语:

  • 已解决 - 意味着它已解决另一个承诺值并正在跟踪它.
  • 已经解决 - 意味着它实际上已经实现或被拒绝 - 要么是通过承诺解决,要么是自己解决.

唷.现在已经不在了:

什么Promise.resolve是创造一个解决另一个价值的承诺.如果该值是一个它跟踪它的一个承诺 - 否则它会立即与传入的值结算.如果你return来自函数中的某个thenawait某个东西,也会发生这种情况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.