为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

江户川乱折腾 2019-05-27 16:20:02
什么时候.then(成功,失败)被认为是承诺的反模式?我看了一下bluebird promise FAQ,其中提到了这.then(success, fail)是一个反模式。我不太了解它对try和catch的解释。以下是什么问题?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) })有什么不同?
查看完整描述

4 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

有什么不同?

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

这是一个控制流程图

https://img1.sycdn.imooc.com//5ceb9e650001270b03000300.jpghttps://img1.sycdn.imooc.com//5ceb9e6500013a1a03000480.jpg

用同步代码表达它:

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

第二个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);}

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

差异太大了。

我不太了解它对try和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()它。


查看完整回答
反对 回复 2019-05-27
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

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

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

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


查看完整回答
反对 回复 2019-05-27
?
慕森王

TA贡献1777条经验 获得超3个赞

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

捕获方法

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

好处

  1. 所有错误都由一个catch块处理。

  2. 甚至在then块中捕获任何异常。

  3. 链接多个成功回调

缺点

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

成功/错误方法

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

好处

  1. 你得到了细粒度的错误控制。

  2. 您可以为各种类型的错误(如db error,500 error等)提供常见的错误处理功能。

Disavantages

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


查看完整回答
反对 回复 2019-05-27
?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

简单解释:

在ES2018中

使用参数onRejected调用catch方法时,将执行以下步骤:

  1. 让我们承诺这个价值。

  2. 回来?调用(promise,“then”,“undefined,onRejected”)。

这意味着:

promise.then(f1).catch(f2)

等于

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


查看完整回答
反对 回复 2019-05-27
  • 4 回答
  • 0 关注
  • 3338 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信