为什么我可以在链的中间得到一个蓝鸟捕捉来停止链的其余执行

Why can I get a Bluebird catch in the middle of chain stop the rest of the chain execution

本文关键字:执行 余执行 蓝鸟 中间 我可以 一个 为什么      更新时间:2023-10-04

我正在构建这个承诺链。目标是让第一个操作检查DB中某个字段的唯一性,然后如果唯一,则保存对象。但是,如果对象不是唯一的,它就不应该保存,并且应该返回一个错误响应。

function(request, reply) {
  var payload = request.payload;
  checkThatEmailDoesNotExist().then(saveUser)
  function checkThatEmailDoesNotExist() {
    return User.where({email: payload.email}).countAsync()
      .then(function(count) {
        if (count > 0) {
          throw Boom.badRequest('The email provided for this user already exists')
        }
        return null;
      })
      .catch(function(err) { // ~This catch should stop the promise chain~
        reply(err);
      })
  }
  function saveUser() {
    // ~But instead it is continuing on to this step~
    return User.massAssign(request.payload).saveAsync()
      .spread(function(user, numAffected) {
        return reply(user);
      })
      .catch(function(err) {
        server.log(['error', 'api', 'auth'], err);
        throw Boom.badRequest('Object could not be saved to database');
      });
  }
}

如果在checkThatEmailDoesNotExist()中抛出错误,它的catch()应该返回错误,并停止处理原始承诺链的其余部分。

catch()没有这样做,而是启动,然后继续执行saveUser()函数。

您混合了promise和callback,这是一种可怕的反模式。呼叫者只需使用返回的promise,不需要手动将事情连接回回调。

function save(request) {
  var payload = request.payload;
    return User.where({email: payload.email}).countAsync()
      .then(function(count) {
        if (count > 0) {
          throw Boom.badRequest('The email provided for this user already exists')
        }
        return User.massAssign(request.payload).saveAsync()
      })
      .get(0)
      /* equivalent to 
      .spread(function(user, numAffected) {
        return user;
      }) */
      .catch(Promise.OperationalError, function(err) {
        server.log(['error', 'api', 'auth'], err);
        throw Boom.badRequest('Object could not be saved to database');
      });
}

用法:

save(request).then(function(user) {
    response.render(...)
}).catch(function(e) {
    response.error(...)
})

如果你想公开一个回调api,明智的方法是在现有promise api的末尾加上一个nodeify,并结束它:

function save(request, callback) {
  var payload = request.payload;
    return User.where({email: payload.email}).countAsync()
      .then(function(count) {
        if (count > 0) {
          throw Boom.badRequest('The email provided for this user already exists')
        }
        return User.massAssign(request.payload).saveAsync()
      })
      .get(0)
      /* equivalent to 
      .spread(function(user, numAffected) {
        return user;
      }) */
      .catch(Promise.OperationalError, function(err) {
        server.log(['error', 'api', 'auth'], err);
        throw Boom.badRequest('Object could not be saved to database');
      })
      .nodeify(callback);
}
save(request, function(err, user) {
    if (err) return response.error(...);
    response.render(...);
});