我是否正确使用了承诺?
Am I using promises correctly?
我有以下功能(我正在使用 Q
promise 库):
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
我写的上面的函数是否符合这些做法,或者有更好的方法吗?
在我看来,您可以将方法重写为:
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()
似乎都在返回 promises(我是从你的代码中推断出来的),所以你可以很容易地用它们创建一个 promise 链。
但即使他们没有返回承诺,您也可能不需要 q.defer()
,如 on this page you already mention ("Rookie mistake #4"). See Q.Promise
所述。
使用 Mongoose(尤其是从版本 4 开始),原生支持 promises,因此您不需要使用 Q。此外,在 Node.js 0.12+ 和 io.js 上,对 Promises 提供了 natie 支持, 所以再次不需要 Q!
这就是我编写该方法的方式(使用本机 Promise;这里 polyfill 如果仍在 Node 0.10 上)
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 方法returns 一个Promise。根据模式,promise 可以是 resolve()
'd 或 reject()
'd
2. User.find 被调用。使用 Mongoose,returns 一个承诺,因此您可以:then(callback, reject)
。因此,如果 User.find returns 出错,则 confirmEmail 返回的 Promise 将被拒绝("outer one")。
3. 如果 User.find 成功,我们继续。如果没有结果(if(user)
为假),那么我们手动拒绝 "outer promise" 并且我们不做任何其他事情。
4. 如果有用户,我们调用 user.updateAttributes
,这也是 returns 一个承诺。因此,我们正在调用 then(resolve, reject)
,因此该承诺的结果将传递给 "outer promise"。
使用示例:
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
})
我有以下功能(我正在使用 Q
promise 库):
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
我写的上面的函数是否符合这些做法,或者有更好的方法吗?
在我看来,您可以将方法重写为:
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()
似乎都在返回 promises(我是从你的代码中推断出来的),所以你可以很容易地用它们创建一个 promise 链。
但即使他们没有返回承诺,您也可能不需要 q.defer()
,如 on this page you already mention ("Rookie mistake #4"). See Q.Promise
所述。
使用 Mongoose(尤其是从版本 4 开始),原生支持 promises,因此您不需要使用 Q。此外,在 Node.js 0.12+ 和 io.js 上,对 Promises 提供了 natie 支持, 所以再次不需要 Q!
这就是我编写该方法的方式(使用本机 Promise;这里 polyfill 如果仍在 Node 0.10 上)
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 方法returns 一个Promise。根据模式,promise 可以是 resolve()
'd 或 reject()
'd
2. User.find 被调用。使用 Mongoose,returns 一个承诺,因此您可以:then(callback, reject)
。因此,如果 User.find returns 出错,则 confirmEmail 返回的 Promise 将被拒绝("outer one")。
3. 如果 User.find 成功,我们继续。如果没有结果(if(user)
为假),那么我们手动拒绝 "outer promise" 并且我们不做任何其他事情。
4. 如果有用户,我们调用 user.updateAttributes
,这也是 returns 一个承诺。因此,我们正在调用 then(resolve, reject)
,因此该承诺的结果将传递给 "outer promise"。
使用示例:
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
})