转发 Promise 导致 Promise 链 - 为什么我得到 Promise 对象而不是拒绝值

Forwarding Promises results in Promise chain - why I get Promise object instead of rejected value

我无法理解转发承诺结果(嵌套承诺)的工作原理。

此代码按我预期的方式工作(最后我得到整数值):

function opThatResolves() {
  return Promise.resolve(1);
}

function opThatWillBeForwarded(x) {
  return new Promise(function(resolve, reject) {
    resolve(yetAnotherNestedPromise(x));
  })
}

function yetAnotherNestedPromise(x) {
  return Promise.resolve(-x);
}

opThatResolves()
  .then(x => opThatWillBeForwarded(x))
  .then(x => x * 2)
  .then(x => x * 2)
  .then(x => console.log("Resolved: " + x))
  .catch(x => console.log("Rejected: " + x))

所以我认为如果我将 resolve 更改为 reject 我会在 catch 块中得到类似的结果(整数值但没有双 *2 乘法)。但是我得到了一个完整的 Promise 对象:

function opThatResolves() {
  return Promise.resolve(1);
}

function opThatWillBeForwarded(x) {
  return new Promise(function(resolve, reject) {
    reject(yetAnotherNestedPromise(x));
  })
}

function yetAnotherNestedPromise(x) {
  return Promise.resolve(-x);
}

opThatResolves()
  .then(x => opThatWillBeForwarded(x))
  .then(x => x * 2)
  .then(x => x * 2)
  .then(x => console.log("Resolved: " + x))
  .catch(x => console.log("Rejected: " + x))

为什么 reject 不像 resolve 那样 "unwrap" 从 yetAnotherNestedPromise 返回的 Promise?

因为它一开始就不应该收到 Promise

reject回调应该包含失败的原因(即Error)。

function opThatResolves() {
  return Promise.resolve(1);
}

function opThatWillBeForwarded(x) {
  return new Promise(function(resolve, reject) {
    reject(new Error("failed"));
  })
}

opThatResolves()
  .then(x => opThatWillBeForwarded(x))
  .then(x => x * 2)
  .then(x => x * 2)
  .then(x => console.log("Resolved: " + x))
  .catch(x => console.log("Rejected: " + x));

请注意,可以通过后续错误回调重新抛出该错误:

new Promise((resolve, reject) => {
    reject(new Error("failed !"));
})
    .then(null, reason => {
        console.log(1, reason);
        throw reason;
    })
    .catch(reason => {
        console.log(2, reason);
    });

另请注意,如果错误回调未能重新抛出错误(或抛出另一个错误),后续 then 方法将启动它们的成功回调:

new Promise((resolve, reject) => {
    reject(new Error("failed !"));
})
    .then(null, reason => {
        console.log(1, reason);
    })
    .then(result => {
        console.log("Success! Let's throw something else...");
        throw new Error("Another failure");
    })
    .catch(reason => {
        console.log(2, reason);
    });