蓝鸟承诺 - 嵌套与拒绝模式

Posted

技术标签:

【中文标题】蓝鸟承诺 - 嵌套与拒绝模式【英文标题】:Bluebird promises - nesting vs rejecting pattern 【发布时间】:2015-05-17 18:23:13 【问题描述】:

我正在开发一个我们使用 Promise 的应用程序。我正在尝试找出更好的模式是什么。

打破 thenables 之间的关注点并在错误时拒绝承诺。然后在 catch 块中处理拒绝。还是在catch块中throw一种新型错误和句柄更好?

Account.findOneAsync(email: request.payload.email)
  .then(function (user) 
    if (user) 
      return user.compareHash(request.payload.password);
     else 
      // Account not found
      return Bpromise.reject('AccountNotFound');
    
  )
  .then(function (validPassword) 
    if (validPassword) 
      return request.auth.jwt.user.sign();
     else 
      // Invalid password
      return Bpromise.reject('InvalidPassword');
    
  )
  .then(function (jwt) 
    var response = reply.success();
    return response.header('authorization', jwt);
  )
  .catch(function (e) 
    if (e === 'AccountNotFound' || e === 'Invalid Password') 
      return reply(Boom.unauthorized('Invalid username/password'));
     else 
      // Perhaps log something like unhandled error
      return reply(Boom.unauthorized('Invalid username/password'));
    
  );

或嵌套有希望。我觉得这只是在“回调地狱”的同一个兔子洞。

Account.findOneAsync(email: request.payload.email)
      .then(function (user) 
        if (user) 
          user.compareHash(request.payload.password)
            .then(function (valid) 
              if (valid) 
                request.server.plugins.jwt.sign()
                  .then(function (jwt) 
                    var response = reply.success();
                    return response.header('authorization', jwt);
                  );
               else 
                // Invalid password
                return reply(Boom.unauthorized('Invalid username/password'));
              
            );
         else 
          // Account not found
          return reply(Boom.unauthorized('Invalid username/password'));
        
      )
      .catch(function (e) 
        console.log(e);
      );

【问题讨论】:

您认为第二种方法有什么好处吗?第一个对我来说看起来好多了。 好吧,如果我采用第一种方法,我想知道什么更好。抛出一个新的错误或拒绝承诺。我想如果我抛出一个错误,我需要将 Error() 子类化以产生像“throw new AccountNotFound()”这样的错误 正如我在几秒钟前发布的答案中所说的那样,我认为惯用的做法是抛出一个错误。没有必要继承 Error。 Error 构造函数接受一个可以使用e.message 进行检查的消息字符串。 所以我现在看到你在第二种方法中得到了什么。您直接将无效结果转换为Boom.unauthorizeds,而不是抛出错误只是为了在之后将其更改为响应。我会考虑这个... 另见Handling multiple catches in promise chain 【参考方案1】:

我认为你可以通过投掷然后接住你的吊杆来获得两全其美的效果。

在这两种方法中你缺少的一件事是,当你已经在 then 处理程序中时,惯用的做法是抛出一个错误,而不是创建并返回一个被拒绝的承诺。在return 语句之后也不需要else 块:

Account.findOneAsync(email: request.payload.email)
  .then(function (user) 
    if (user) 
      return user.compareHash(request.payload.password);
    
    // Account not found
    throw Boom.unauthorized('Invalid username/password');
  )
  .then(function (validPassword) 
    if (validPassword) 
      return request.auth.jwt.user.sign();
    
    // Invalid password
    throw Boom.unauthorized('Invalid username/password');
  )
  .then(function (jwt) 
    var response = reply.success();
    return response.header('authorization', jwt);
  )
  .catch(function (e) 
    if (e.isBoom) 
      return reply(e);
    
    // Perhaps log something like unhandled error
    return reply(Boom.unauthorized('Invalid username/password'));
  );

【讨论】:

我实际上不得不在第一个 thenable 中测试 request.auth.jwt.user.sign()。主要是因为我在签署 jwt 时需要访问用户对象。鉴于 Promise 规范不允许返回多个值,我觉得以这种方式实现更安全。

以上是关于蓝鸟承诺 - 嵌套与拒绝模式的主要内容,如果未能解决你的问题,请参考以下文章

处理嵌套承诺的最佳方法(蓝鸟)[重复]

承诺按顺序运行嵌套承诺并在第一次拒绝时解决

嵌套承诺和拒绝

与蓝鸟的承诺链阵列

猫鼬承诺与蓝鸟和打字稿

蓝鸟承诺未定义?