我看了一下bluebird承诺常见问题,其中提到。then(成功,失败)是一个反模式。我不太明白它对试捕的解释。 下面有什么问题吗?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

这个例子似乎在暗示下面的方法是正确的。

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

有什么不同?


当前回答

有什么不同?

then()调用将返回一个promise,当回调抛出错误时,该promise将被拒绝。这意味着,当成功记录器失败时,错误将被传递给下面的.catch()回调,而不是传递给与成功并行的失败回调。

这是一个控制流程图:

用同步代码表示:

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

第二个日志(类似于.then()的第一个参数)只会在没有发生异常的情况下执行。带标签的块和break语句感觉有点奇怪,这实际上是python有try-except-else的用途(推荐阅读!)

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

catch记录器还将处理来自成功记录器调用的异常。

差别就这么多了。

我不太明白它对试捕的解释

论点是,通常情况下,您希望在处理的每个步骤中捕获错误,并且不应该在链中使用它。期望只有一个最终处理程序处理所有错误——而当使用“反模式”时,一些当时回调中的错误不会被处理。

然而,这种模式实际上非常有用:当你想要处理恰好在这一步中发生的错误时,当没有发生错误时,你想要做一些完全不同的事情——即当错误不可恢复时。请注意,这是在分支控制流。当然,这有时是需要的。


下面有什么问题吗? some_promise_call () .then(function(res) {logger.log(res)}, function(err) {logger.log(err)})

你必须重复你的回调。你宁愿要

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

你也可以考虑使用.finally()。

其他回答

好例子,而不是文字。以下代码(如果第一个承诺已解决):

Promise.resolve()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

等于:

Promise.resolve()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)

但与被拒绝的第一个承诺不同,这是不一样的:

Promise.reject()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

Promise.reject()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)

这两者并不完全相同。不同之处在于,第一个示例不会捕获成功处理程序中抛出的异常。因此,如果您的方法应该只返回已解决的承诺(通常是这种情况),则需要一个尾随catch处理程序(或者另一个带有空成功参数的then)。当然,可能您的then处理程序没有做任何可能失败的事情,在这种情况下,使用一个2参数then可能很好。

但我相信你链接到的文本的观点是,然后是最有用的,而不是回调在它的能力链一堆异步步骤,当你实际上这样做,然后的2参数形式微妙地不像预期的那样表现,出于上述原因。当使用中链时,这尤其违反直觉。

作为一个做过很多复杂的异步工作的人,我真的建议避免这种反模式,使用单独的处理程序方法。

简单的解释:

在ES2018

当使用参数onRejected调用catch方法时, 采取以下步骤: 让承诺成为这份价值。 回报呢?Invoke(promise, "then",«undefined, onRejected»)。

这意味着:

promise.then(f1).catch(f2)

=

promise.then(f1).then(undefiend, f2)

有什么不同?

then()调用将返回一个promise,当回调抛出错误时,该promise将被拒绝。这意味着,当成功记录器失败时,错误将被传递给下面的.catch()回调,而不是传递给与成功并行的失败回调。

这是一个控制流程图:

用同步代码表示:

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

第二个日志(类似于.then()的第一个参数)只会在没有发生异常的情况下执行。带标签的块和break语句感觉有点奇怪,这实际上是python有try-except-else的用途(推荐阅读!)

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

catch记录器还将处理来自成功记录器调用的异常。

差别就这么多了。

我不太明白它对试捕的解释

论点是,通常情况下,您希望在处理的每个步骤中捕获错误,并且不应该在链中使用它。期望只有一个最终处理程序处理所有错误——而当使用“反模式”时,一些当时回调中的错误不会被处理。

然而,这种模式实际上非常有用:当你想要处理恰好在这一步中发生的错误时,当没有发生错误时,你想要做一些完全不同的事情——即当错误不可恢复时。请注意,这是在分支控制流。当然,这有时是需要的。


下面有什么问题吗? some_promise_call () .then(function(res) {logger.log(res)}, function(err) {logger.log(err)})

你必须重复你的回调。你宁愿要

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

你也可以考虑使用.finally()。

通过观察两者的优点和缺点,我们可以计算出哪种适合这种情况。 这是实现承诺的两种主要方法。两者都有优点和缺点

捕捉方法

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

优势

所有错误都由一个catch块处理。 Even捕获then块中的任何异常。 多个成功回调的链接

缺点

在链接的情况下,很难显示不同的错误消息。

成功/错误的方法

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })

优势

你得到了细粒度的错误控制。 你可以使用常见的错误处理功能来处理各种类型的错误,比如db错误,500错误等等。

Disavantages

如果希望处理成功回调抛出的错误,仍然需要另一个catch