我有以下功能(我使用Q
承诺库):
confirmEmail: function(confirmationCode){
var deferred = q.defer();
User.find({
where: {confirmation_code: confirmationCode}
}).then(function(user){
if(user){
user.updateAttributes({
confirmation_code : null,
confirmed: true
}).then(function() {
deferred.resolve();
});
}else{
deferred.reject(new Error('Invalid confirmation code'));
}
});
return deferred.promise;
}
我一直在阅读有关承诺的最佳做法,例如: What is the explicit promise construction antipattern and how do I avoid it? http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
我是否已编写上述功能以使其符合这些惯例,还是有更好的方法?
答案 0 :(得分:3)
在我看来,你可以改写你的方法:
confirmEmail : function(confirmationCode) {
return User.find({
where : { confirmation_code : confirmationCode }
}).then(function(user) {
if (! user) {
throw new Error('Invalid confirmation code');
}
return user.updateAttributes({
confirmation_code : null,
confirmed : true
});
});
}
User.find()
和user.updateAttributes()
似乎都在返回承诺(我在您的代码中推断这一点),因此您可以轻松地使用它们创建承诺链。
但即使他们没有回复承诺,你也可能不需要q.defer()
,如概述on this page you already mention(“新手错误#4”)。请参阅Q.Promise
。
答案 1 :(得分:0)
使用Mongoose(尤其是版本4),本机支持promises,因此您不需要使用Q.此外,在Node.js 0.12+和io.js上有对Promises的natie支持,所以再次不需要!Q
这就是我编写方法的方法(使用本机Promise;如果仍然在节点0.10上,这里是polyfill)
confirmEmail: function(confirmationCode){
return new Promise(function(resolve, reject) {
User.find({
where: {confirmation_code: confirmationCode}
})
.then(function(user) {
if(user){
user.updateAttributes({
confirmation_code : null,
confirmed: true
})
.then(resolve, reject)
}
else {
reject(new Error('Invalid confirmation code'))
}
}, reject)
})
}
工作原理:
1. confirmEmail方法返回一个Promise。根据模式,承诺可以是resolve()
'd或reject()
'd
2.调用User.find。使用Mongoose,它会返回一个promise,因此您可以执行:then(callback, reject)
。因此,如果User.find返回错误,则confirmEmail返回的Promise将被拒绝(“外部的”)。
3.如果User.find成功,我们继续。如果没有结果(if(user)
为假),那么我们手动拒绝“外部承诺”,我们不做任何其他事情。
4.如果有用户,我们会调用user.updateAttributes
,这也会返回一个承诺。我们因此调用then(resolve, reject)
,因此该承诺的结果将传递给“外部承诺”。
使用示例:
obj.confirmEmail(confirmationCode).
.then(function(user) {
// Everything went fine
}, function(error) {
// This is invoked if: User.find() failed, or if no result was obtained (with the error "Invalid confirmation code") or if user.updateAttributes failed
})