【问题标题】:Promise's second .then() not failing [duplicate]Promise 的第二个 .then() 没有失败 [重复]
【发布时间】:2014-07-19 13:09:10
【问题描述】:

我在链接 .then() 请求时遇到问题。执行以下代码时:

var prom = new Promise(function(resolve, reject) {
  //let's always fail
  reject(Error("buuuu!"));
});

var thenable = 
prom.then(
    function(done) {
        console.log("First handler: Done!: Argument: ", done);
        return "First then: DONE";
    },
    function(fail) {
        console.error("First handler: Fail!. Argument: ", fail);
        return "First then: FAIL";
    }
).then(
    function(done) {
        console.info("Second handler: Done!.  Argument: ", done);
    },
    function(fail) {
        console.error("Second handler: Fail!.  Argument: ", fail);
    }
);

这会在控制台中打印以下内容:

First handler: Fail!. Argument:  Error {stack: (...), message: "buuuu!"}
Second handler: Done!.  Argument:  First then: FAIL


为什么第二个 then() 调用的是 done 处理程序而不是 fail 处理程序?

这是 Chrome 的错误吗? (请注意,我只对 Google Chrome 的行为感兴趣)

我是否需要从 .then 处理程序返回预先解决/拒绝的承诺?

【问题讨论】:

    标签: javascript google-chrome promise


    【解决方案1】:

    为什么第二个 then() 调用了它的 done 处理程序而不是 fail 处理程序?

    因为您已经处理了链的第一个 then() 中的错误,所以使用您从它返回的 "First then: FAIL" 字符串解析承诺。

    这是 Chrome 的错误吗?

    不,promise 应该是这样工作的。

    我是否需要从 .then 处理程序返回预先解决/拒绝的 Promise?

    你可以这样做,是的。触发第二个失败处理程序的其他方法是:

    • 只需省略第一个错误处理程序:

      prom.then(function(done) {
          console.log("First handler: Done!: Argument: ", done);
          return "First then: DONE";
      }).then(function(done) {
          console.info("Second handler: Done!.  Argument: ", done);
      }, function(fail) {
          console.error("Second handler: Fail!.  Argument: ", fail);
      });
      
    • 或者重新抛出一个异常(这类似于返回一个被拒绝的承诺):

      prom.then(function(done) {
          console.log("First handler: Done!: Argument: ", done);
          return "First then: DONE";
      }, function(fail) {
          console.error("First handler: Fail!. Argument: ", fail);
          throw new Error("First then: FAIL"); // or: throw fail;
          // alternatively, you can return a rejected promise:
          return Promise.reject(new Error("First then: FAIL"));
      }).then(function(done) {
          console.info("Second handler: Done!.  Argument: ", done);
      }, function(fail) {
          console.error("Second handler: Fail!.  Argument: ", fail);
      });
      

    【讨论】:

    • 或者在失败的情况下你可以只返回被拒绝的承诺。
    • 你的意思是return prom?是的,这可能也可以,但有点奇怪。您可能会立即将两个处理程序附加到它:prom.then(donehandler1, failhandler1); prom.then(donehandler2, failhandler2);
    • 谢谢!我有点假设“失败”的情况会在整个链条中持续存在。
    • 另外,如果我没记错的话,直接在prom 上调用.then 两次会使两者同步执行,而不是链接.then().then()
    • 好吧,它会在链上冒泡(“持续”)直到它被处理。是的,在同一个 promise 上调用 then 两次确实会“分叉”执行流程。不确定您需要什么,您需要发布真实世界的代码而不是示例。
    【解决方案2】:

    为什么第二个 then() 调用了它的 done 处理程序而不是 fail 处理程序?

    让我们看看你的代码在同步世界中的样子:

    var value;
    try{
        try {
            throw new Error("buuu!");
            console.log("First handler: Done!: Argument: ");
            value = "First then: DONE";
        } catch(e){
            console.error("First handler: Fail!. Argument: ", e);
            value = "First then: FAIL";
        }
        console.info("Second handler: Done!.  Argument: ", value);
    }catch(e){
        console.error("Second handler: Fail!.  Argument: ", e);
    }
    

    当您在 catch 子句中处理错误时,就像您在 then 子句中处理错误时一样,您从中恢复。 Promise 示例与我们的同步示例完全相同。

    如果您想表明您执行了恢复逻辑但仍处于链上的拒绝状态,请重新抛出。这就是在同步代码中总是这样做的。

    【讨论】:

    • 谢谢!你的答案同样好,但另一个是第一个。无论如何,我给了你一个赞成票
    • 我也给了另一个答案 :) 我只是想给出与同步检查相比的观点。
    • +1。我曾考虑在我的回答中加入这个类比,但不知何故知道@BenjaminGruenbaum 不可避免的回答会采取这种解释方式:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2017-02-25
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2019-11-16
    • 2021-10-17
    相关资源
    最近更新 更多