为什么我可以在链式链接中间得到一只蓝鸟捕捉其余的链式执行
问题描述:
我正在构建这个承诺链。目标是让第一个操作检查数据库中字段的唯一性,然后如果唯一,请保存该对象。但是如果对象不是唯一的,它不应该保存,并且应该返回错误响应。为什么我可以在链式链接中间得到一只蓝鸟捕捉其余的链式执行
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()
函数。
答
你在混合承诺和回调,这是一个可怕的反模式。来电者只需使用 返回的承诺,不需要手动将事情回传给回叫。
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(...);
});
捕获收益“成功”并返回已解决(履行)的承诺。所以链接'然后'的**将被执行。为了避免这种情况,请在'catch'函数内再次抛出错误。换句话说,你可以说拒绝只会沿着链条被捕获一次(除非catch处理程序本身反复抛出)。顺便说一下,这是在某些人承诺应该使用的边界上。通常,拒绝表示一些特殊情况。在这里,您正在使用它们进行一些普通的旧重复检查。 – 2015-02-12 12:35:47