蓝鸟承诺并抓住分支

Bluebird promises and catch branching

我想知道 Bluebird 中是否有一种方法可以承诺 .catch 抛出的错误,然后在不使用分支(嵌套承诺)的情况下处理一些特定的操作。

说我有

doSomethingAsync()
.then(function (result) {
  if (!result)
    throw new CustomError('Blah Blah');

  if (result == 0)
    throw new CustomError2('Blah Blah Blah');

  return result;
})
.then(function (result) {
  console.log('Success, great!');
})

.catch(CustomError, function (error) {
  // Oh CustomError!
  return saveSomethingAsync();
})
.then(function (saved) {
  // Should only be executed if an CustomError has been thrown
  console.log("Let's try again");
  return doSomethingAsync();
})

.catch(CustomError2, function (error) {
  // Oh CustomError2!
})
.delay(15000) // Don't try again now !
.then(function () {
  // Should only be executed if an CustomError2 has been thrown
  console.log("Let's try again after some long delay");
  return doSomethingAsync();
})

.catch(function (error) {
  // Should catch all random errors of the chain
})

当我执行这段代码时,我得到了几个行为:

我不知道这个流程发生了什么。 写这样的东西应该很棒,而不是将错误的特定代码嵌套在新的承诺链中。

.catch a thrown error and then process some specific actions without branching

没有。因为 分支。嵌套在这里是完全自然的。您甚至可以使用同步-try-catch 隐喻来考虑这一点,它是相同的。

I can't figure out what's happening with this flow.

  • If no error is thrown, I get "Success, great!" and it start again with "Let's try again after some long delay"

嗯,这很奇怪,因为 "Let's try again"(没有延迟)在此之前链接。你最终应该得到这两个日志。您的链按顺序处理:

doSomethingAsync() // returns a result
 then return result // first callback: continues with it
 then console.log('Success, great!') // next callback: logs something
 catch // is ignored because no rejection
 then console.log("Let's try again"); // next callback: logs something
      return doSomethingAsync();      //                and returns a result
 catch // that result, not being a rejection, is ignored here
 delay // fulfillment is delayed
 then console.log("Let's try again after some long delay"); // next callback again logs
      return doSomethingAsync();                            // and returns a result
 catch // is ignored again
  • If a CustomError is thrown, I get "Let's try again"

是的,因为 saveSomethingAsync();,之前承诺的结果已经实现,所以执行链中的下一个 .then() 回调。

  • If a CustomError2 is thrown, I get "Let's try again after some long delay"

是的,因为错误一直冒到 .catch(CustomError2, …) 最终得到处理。在途中,没有执行任何回调。在 the error was handled 之后,promise 被履行,链中的下一个 .then() 调用它的回调。

我想你真正想要的是

doSomethingAsync()
.then(function(result) {
  if (!result)
    // CustomError('Blah Blah');
    // Oh CustomError!
    return saveSomethingAsync();
    .then(function(saved) {
      console.log("Let's try again");
      return doSomethingAsync();
    });
  else if (result == 0)
    // CustomError2('Blah Blah Blah');
    // Oh CustomError2!
    return Promise.delay(15000) // Don't try again now !
    .then(function() {
      console.log("Let's try again after some long delay");
      return doSomethingAsync();
    })
  else
    console.log('Success, great!');
  // return undefined implied
}).catch(function (error) {
  // does catch all random errors of the chain
  // thrown by any of the doSomethingAsync() or of the saveSomethingAsync
})