Bluebird promises - 嵌套与拒绝模式

Bluebird promises - nesting vs rejecting pattern

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

消除 thenables 之间的顾虑,并在出现错误时拒绝承诺。然后在 catch 块中处理拒绝。还是 throw 一种新的错误类型并在 catch 块中处理更好?

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

或嵌套承诺本身。不过,我觉得这只是陷入了 "callback hell" 的同一个兔子洞。

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

我认为您可以通过抛出然后接住吊杆物体来两全其美。

您在这两种方法中都缺少的一件事是,当您已经在 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'));
  });