promises上的then()方法返回一个promise。承诺可以处于三种状态之一,待决,履行或拒绝。但是,在创建承诺时,如果您希望履行或拒绝承诺,则可以使用已解决和拒绝的方法进行调用。我无法在then()方法中找到如何在函数上使用这些方法。当我尝试在then()链中间使用带有回调的普通异步函数时,这会给我带来问题。以此代码为例。
User.findOne({
where: {
email: email
}
}).then(function(user){
if(user){
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}else{
var user = User.build({ email: email });
console.log("ONE");
User.generateHash(password, function(err, hash){
console.log("TWO");
if(err){
return done(err);
}else{
user.password = hash;
var newUser = user.save();
return newUser;
}
})
}
}, function(err){
console.log("ERROR: ", err);
}).then(function(newUser){
console.log("THREE");
return done(null, newUser);
}, function(err){
console.log("USER NOT CREATED: ", err);
});
在这种情况下,User.findOne()返回一个promise。现在,这个控制台将打印三个两个。一旦调用异步,就会调用第二个then语句。有没有办法在我通知它已解决之前没有调用第二个语句。
(我知道这将是修复几种不同方式的简单代码,我更好奇为什么以及第一个语句返回的当时承诺何时变为满足。)
答案 0 :(得分:2)
所以会发生什么,findUser
得到满足(并且没有被拒绝),因此.then()
的第一个参数中的回调会调用(而不是第二个)。
在.then()
子句中,您console.log("ONE")
并且您没有返回任何内容(因为您属于else {
子句,并且您只返回到createHash
的回调在承诺的背景下意义重大。),所以它实际上返回undefined
。
然后下一个.then()
调用,你得到console.log("THREE")
。
然后在将来的某个时间,您会从createHash
调用回调,然后获得console.log("TWO")
。
正确的方法是编写User.generateHash
以便它也返回一个promise,然后你可以将它与promise链的其余部分链接起来,而不必处理promise promise回调中的异步内容。
答案 1 :(得分:1)
创建承诺时,如果您希望履行或拒绝承诺,则可以使用已解决和拒绝的方法进行调用。我无法在then()方法
中找到如何在函数上使用这些方法
在承诺上使用then
方法时,您无权访问resolve
/ reject
回调 - then
为您管理所有这些。它确实返回了新的promise,它将使用回调的 result 解析,即其返回值。此返回值可以是将自动同化的承诺(当您使用承诺解决时,它将自动履行/拒绝承诺的结果)。
所以这就是你需要做的。如果要在then
回调中调用回调方法,则必须为其创建承诺,然后可以return
。最简单,最好的方法是事先promisify the callback function,但您也可以使用Promise
构造函数(您可以访问resolve
/ reject
)。< / p>
User.findOne({
where: {
email: email
}
}).then(function(user){
if (user){
throw new Error('That email is already taken.');
} else {
var user = User.build({ email: email });
console.log("ONE");
var promise = new Promise(function(resolve, reject) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
User.generateHash(password, function(err, hash){
if (err) reject(err);
else resolve(hash);
});
return promise.then(function(hash) {
console.log("TWO");
user.password = hash;
var newUser = user.save();
return newUser;
});
}
}).then(function(newUser){
console.log("THREE");
return done(null, newUser);
}, function(err){
console.log("ERROR: ", err);
return done(null, false, req.flash('signupMessage', err.message));
});
答案 2 :(得分:0)
如果done()和User.generateHash()没有返回promises,那么在进入下一个then()块之前没有理由让这个程序的第二级等待。
为了解决这个问题,或者看到你的打印报告打印出一两个,我会这样做
User.findOne({
where: {
email: email
}
}).then(function(user){
var promise;
if(user){
promise = done(null, false, req.flash('signupMessage', 'That email is already taken.'));
}else{
var user = User.build({ email: email });
console.log("ONE");
promise = User.generateHash(password, function(err, hash){
return new Promise(function(resolve, reject){
console.log("TWO");
if(err){
reject(done(err));
}else{
user.password = hash;
var newUser = user.save();
resolve(newUser);
}
});
});
}
return promise;
}, function(err){
console.log("ERROR: ", err);
}).then(function(newUser){
console.log("THREE");
return done(null, newUser);
}, function(err){
console.log("USER NOT CREATED: ", err);
});
这样第一个将等待promise被解析,然后进入下一个块,这意味着User.generateHash必须在进入下一个块之前解析,因为变量promise取决于它。