使用 Q 在 Node.js 中同步承诺时遇到问题
Trouble to synchronise promises in Node.js using Q
我目前正在 Node.JS 中使用框架 Sails.js 做一个 API。我是第一次使用 promises,我在同步我的 promises 时遇到了一些麻烦。
我的主要功能如下:
createCard: function(req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount())
.then(function cardCreated() {
res.send(200, {
msg: 'Card created'
});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
显然,如果用户没有信用卡,我无法将信用卡添加到条纹帐户。
函数 checkIfUserHasStripeAccount() 检查帐户是否存在,如果不存在,则创建它。
这是这部分的代码:
function checkIfUserHasStripeAccount(user) {
var deferred = q.defer();
if (!user.idStripe) {
createStripeAccountToUser(user)
.then(function(savedUser) {
deferred.resolve(savedUser);
})
.catch(function(err) {
deferred.reject(err);
})
} else {
deferred.resolve(user);
}
return deferred.promise;
}
function createStripeAccountToUser(user) {
var deferred = q.defer();
var jsonUserToCreate = {
description: user.firstname + ' ' + user.surname,
email: user.email
};
stripe.customers.create(jsonUserToCreate, function(err, customer) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
} else {
user.idStripe = customer.id;
user.save(function(err, savedUser) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
}
deferred.resolve(savedUser);
});
}
});
return deferred.promise;
}
问题是 .then(addCreditCardToStripeAccount())
在 checkIfUserHasStripeAccount()
完成之前执行。
我不明白为什么。我认为 .then(addCreditCardToStripeAccount())
只有在收到拒绝或解决时才会执行。
你的思路是对的。
问题是您正在调用您的函数而不是引用它:
.then(addCreditCardToStripeAccount())
应该是:
.then(addCreditCardToStripeAccount)
我希望它能起作用:
createCard: function (req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount)
.then(function cardCreated(){
res.send(200, {msg: 'Card created'});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
为了将来,请注意函数名称后的 ()
调用函数,因为 JS 中的执行顺序将首先评估它,因为它位于 then 的 ()
.[=16= 中]
在承诺链中,始终只调用第一个函数。示例:
function first () { /*...*/ } // All return promise.
function second() { /*...*/ }
function third () { /*...*/ }
first() // Invoked
.then(second) // Not invoked. second() will have been bad here.
.then(third);
我目前正在 Node.JS 中使用框架 Sails.js 做一个 API。我是第一次使用 promises,我在同步我的 promises 时遇到了一些麻烦。
我的主要功能如下:
createCard: function(req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount())
.then(function cardCreated() {
res.send(200, {
msg: 'Card created'
});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
显然,如果用户没有信用卡,我无法将信用卡添加到条纹帐户。
函数 checkIfUserHasStripeAccount() 检查帐户是否存在,如果不存在,则创建它。
这是这部分的代码:
function checkIfUserHasStripeAccount(user) {
var deferred = q.defer();
if (!user.idStripe) {
createStripeAccountToUser(user)
.then(function(savedUser) {
deferred.resolve(savedUser);
})
.catch(function(err) {
deferred.reject(err);
})
} else {
deferred.resolve(user);
}
return deferred.promise;
}
function createStripeAccountToUser(user) {
var deferred = q.defer();
var jsonUserToCreate = {
description: user.firstname + ' ' + user.surname,
email: user.email
};
stripe.customers.create(jsonUserToCreate, function(err, customer) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
} else {
user.idStripe = customer.id;
user.save(function(err, savedUser) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
}
deferred.resolve(savedUser);
});
}
});
return deferred.promise;
}
问题是 .then(addCreditCardToStripeAccount())
在 checkIfUserHasStripeAccount()
完成之前执行。
我不明白为什么。我认为 .then(addCreditCardToStripeAccount())
只有在收到拒绝或解决时才会执行。
你的思路是对的。 问题是您正在调用您的函数而不是引用它:
.then(addCreditCardToStripeAccount())
应该是:
.then(addCreditCardToStripeAccount)
我希望它能起作用:
createCard: function (req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount)
.then(function cardCreated(){
res.send(200, {msg: 'Card created'});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
为了将来,请注意函数名称后的 ()
调用函数,因为 JS 中的执行顺序将首先评估它,因为它位于 then 的 ()
.[=16= 中]
在承诺链中,始终只调用第一个函数。示例:
function first () { /*...*/ } // All return promise.
function second() { /*...*/ }
function third () { /*...*/ }
first() // Invoked
.then(second) // Not invoked. second() will have been bad here.
.then(third);