我看了一下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) })

有什么不同?


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

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

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


有什么不同?

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


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

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'); }
)

简单的解释:

在ES2018

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

这意味着:

promise.then(f1).catch(f2)

=

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

Using .then().catch() lets you enable Promise Chaining which is required to fulfil a workflow. You may need to read some information from database then you want to pass it to an async API then you want to manipulate the response. You may want to push the response back into the database. Handling all these workflows with your concept is doable but very hard to manage. The better solution will be then().then().then().then().catch() which receives all errors in just once catch and lets you keep the maintainability of the code.


使用then()和catch()有助于连接promise上的成功和失败处理程序。catch()对then()返回的promise有效。它处理,

如果承诺被拒绝。见图中的第三条 如果在then()的成功处理程序中发生错误,则在下面的行号4到7之间。看到# 2。图片中的A (then()上的失败回调不会处理这个。) 如果在then()的失败处理程序中发生错误,则下面的第8行。看到# 3。B在照片上。

1. let promiseRef: Promise = this。aTimetakingTask(假); 2. promiseRef 3 .不要犹豫( 4. (result) => { 5. /*成功,决心承诺。 6. 在这里处理数据*/ 7. }, 8. (error) => console.log(error) 9)。 10. .catch((e) => { 11. /*成功,决心承诺。 12. 在这里处理数据*/ 13. });

注意:很多时候,如果catch()是,则可能没有定义失败处理程序 已经写的。 EDIT: reject()只会在出现错误时调用catch() then()中的处理程序没有定义。注意图片中的第三条 问题()。当第8行和第9行中的处理程序没有被调用时,将调用它 定义的。

这是有意义的,因为如果由回调处理,那么then()返回的promise不会有错误。