什么时候.then(成功,失败)被认为是承诺的反模式?

use*_*480 167 javascript node.js promise bluebird

我看了一下bluebird promise FAQ,其中提到了这.then(success, fail)是一个反模式.我不太了解它对try和catch的解释.以下是什么问题?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Run Code Online (Sandbox Code Playgroud)

似乎这个例子建议以下是正确的方法.

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Run Code Online (Sandbox Code Playgroud)

有什么不同?

Ber*_*rgi 195

有什么不同?

.then()调用将返回一个承诺,如果回调引发错误,将拒绝该承诺.这意味着,当您的成功logger失败时,错误将传递给以下.catch()回调,但不会传递给fail与之并行的回调success.

这是一个控制流程图:

然后用两个参数控制流程图 控制流程图然后捕获链

用同步代码表达它:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

第二个log(就像第一个参数一样.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);
}
Run Code Online (Sandbox Code Playgroud)

catch记录仪也将处理来自成功记录通话例外.

差异太大了.

我不太了解它对try和catch的解释

通常,您希望在处理的每个步骤中捕获错误,并且不应在链中使用它.期望您只有一个处理所有错误的最终处理程序 - 而当您使用"反模式"时,某些后续回调中的错误不会被处理.

但是,这种模式实际上非常有用:当您想要处理恰好在此步骤中发生的错误时,并且您希望在没有错误发生时执行完全不同的操作 - 即错误无法恢复时.请注意,这是分支您的控制流程.当然,这有时是期望的.


以下是什么问题?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Run Code Online (Sandbox Code Playgroud)

你不得不重复你的回调.你宁愿想要

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

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

  • 这是**最有用的解释**我几天后就读过了(我已经阅读了很多).我无法解释我是多么感激!:)我认为你应该更多地强调两者之间的区别,即.catch`即使在成功函数内也会捕获错误**..就个人而言,我发现这非常错误,因为你最终得到一个错误输入点,这可以从多个动作中获得多个错误,但这是我的问题.无论如何 - 感谢您的信息!你有没有一些你愿意分享的在线交流工具,所以我可以问更多的东西?:P (7认同)
  • 我希望[this](/sf/answers/3401359181/)在这里给你一些更多的赞成.绝对是本网站上一位重要的"承诺"机制的最佳解释之一. (2认同)
  • `.done()` 不是标准的一部分,是吗?至少 MDN 没有列出那个方法。这会很有帮助。 (2认同)
  • 只是色盲人士的注释:这些图表毫无意义:) (2认同)

acj*_*jay 36

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

但我相信你链接到的文本的重点then在于它能够链接一堆异步步骤的回调,当你实际执行此操作时,2参数形式的then巧妙表现并不像预期的那样,由于上述原因.使用中链时,它特别违反直觉.

作为一个做了很多复杂的异步事情并且碰到这样的角落的人比我承认的更多,我真的建议避免这种反模式并采用单独的处理程序方法.


aWe*_*per 18

通过观察两者的优点和缺点,我们可以对哪种情况做出适当的猜测.这是实施承诺的两种主要方法.两者都有它的优缺点

捕获方法

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Run Code Online (Sandbox Code Playgroud)

好处

  1. 所有错误都由一个catch块处理.
  2. 甚至在then块中捕获任何异常.
  3. 链接多个成功回调

缺点

  1. 在链接的情况下,变得难以显示不同的错误消息.

成功/错误方法

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })
Run Code Online (Sandbox Code Playgroud)

好处

  1. 你得到了细粒度的错误控制.
  2. 您可以为各种类型的错误(如db error,500 error等)提供常见的错误处理功能.

Disavantages

  1. catch如果您希望处理成功回调引发的错误,您仍然需要另一个