2015-02-12 38 views
0

我正在构建这个承诺链。目标是让第一个操作检查数据库中字段的唯一性,然后如果唯一,请保存该对象。但是如果对象不是唯一的,它不应该保存,并且应该返回错误响应。为什么我可以在链式链接中间得到一只蓝鸟捕捉其余的链式执行

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()函数。

+1

捕获收益“成功”并返回已解决(履行)的承诺。所以链接'然后'的**将被执行。为了避免这种情况,请在'catch'函数内再次抛出错误。换句话说,你可以说拒绝只会沿着链条被捕获一次(除非catch处理程序本身反复抛出)。顺便说一下,这是在某些人承诺应该使用的边界上。通常,拒绝表示一些特殊情况。在这里,您正在使用它们进行一些普通的旧重复检查。 – 2015-02-12 12:35:47

回答

0

你在混合承诺和回调,这是一个可怕的反模式。来电者只需使用 返回的承诺,不需要手动将事情回传给回叫。

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,理智的方式做到这一点是在现有承诺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(...); 
}); 
相关问题