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

Javascript 什么时候.then(成功,失败)被认为是承诺的反模式?,javascript,node.js,promise,bluebird,Javascript,Node.js,Promise,Bluebird,我看了一下,里面提到了。我不太明白它对“捉迷藏”的解释。 这有什么问题吗 some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) }) some\u promise\u call() .then(函数(res){logger.log(res)},函数(err){logger.log(err)}) 这个例子似乎表明以下是正确的方法 some\u promise\u

我看了一下,里面提到了。我不太明白它对“捉迷藏”的解释。 这有什么问题吗

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
some\u promise\u call()
.then(函数(res){logger.log(res)},函数(err){logger.log(err)})
这个例子似乎表明以下是正确的方法

some\u promise\u call()
.then(函数(res){logger.log(res)})
.catch(函数(err){logger.log(err)})

有什么不同吗?

这两个不完全相同。区别在于第一个示例不会捕获在
success
处理程序中抛出的异常。因此,如果您的方法应该只返回已解析的承诺,通常情况下,您需要一个跟踪的
catch
处理程序(或者另一个
then
带有空的
success
参数)。当然,可能是您的
then
处理程序没有执行任何可能失败的操作,在这种情况下,使用一个2参数
then
就可以了

但是我相信您链接到的文本的要点是,
then
在链接一系列异步步骤的能力方面比回调更有用,而且当您实际这样做时,
then
的2参数形式微妙地表现出与预期不符的行为,原因如上所述。当使用中链时,它特别违反直觉

作为一个做过很多复杂异步工作的人,我不愿意承认,他遇到了很多这样的麻烦,我真的建议避免这种反模式,使用单独的处理程序方法

有什么区别

.then()
调用将返回一个承诺,如果回调抛出错误,该承诺将被拒绝。这意味着,当成功
记录器
失败时,错误将传递给以下
.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
语句感觉有点奇怪,这实际上就是(推荐阅读!)

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

差别就这么多了

我不太明白它对“捉迷藏”的解释

其理由是,通常您希望在处理的每个步骤中捕获错误,并且不应该在链中使用它。我们的期望是,您只有一个处理所有错误的最终处理程序,而当您使用“反模式”时,一些then回调中的错误不会得到处理

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


这有什么问题吗

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

<>你也可以考虑用这个。

通过查看两者的优缺点,我们可以计算出哪种情况适合哪种情况。 这是实现承诺的两个主要途径。两者都有加号和减号

接球法

优势

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

  • 在链接的情况下,很难显示不同的错误消息
  • 成功/错误方法

    优势

  • 您可以获得细粒度的错误控制
  • 您可以为各种类型的错误(如db错误、500错误等)提供通用的错误处理功能
  • 缺点

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

  • 好的例子代替了文字。以下代码(如果解决了第一个承诺):

    Promise.resolve()
    .那么
    (
    ()=>{抛出新错误('Error occurses');},
    err=>console.log('捕获到此错误:',err)
    );
    
    与以下内容相同:

    Promise.resolve()
    .接住
    (
    err=>console.log('捕获到此错误:',err)
    )
    .那么
    (
    ()=>{抛出新错误('错误发生');}
    )
    
    但对于被拒绝的第一个承诺,这并不相同:

    Promise.reject()
    .那么
    (
    ()=>{抛出新错误('Error occurses');},
    err=>console.log('捕获到此错误:',err)
    );
    承诺,拒绝
    .接住
    (
    err=>console.log('捕获到此错误:',err)
    )
    .那么
    (
    ()=>{抛出新错误('错误发生');}
    )
    
    简单解释:

    2018年欧洲标准日

    当使用参数onRejected调用catch方法时 采取了以下步骤:

  • 让承诺成为这个价值观的核心
  • 返回?调用(承诺,“然后”«未定义,onRejected»)
  • 这意味着:

    promise.then(f1).catch(f2)
    
    相等于

    promise.then(f1).then(undefiend, f2)
    
    使用
    .then().catch()
    可以启用履行工作流所需的承诺链接。您可能需要从数据库中读取一些信息,然后将其传递给异步API,然后操作响应。您可能希望将响应推回到数据库中。用您的概念处理所有这些工作流是可行的,但很难管理。更好的解决方案是
    then().then().then().catch()
    ,它在一次catch中接收所有错误,并让您保持可维护性
    promise.then(f1).catch(f2)
    
    promise.then(f1).then(undefiend, f2)