使用Q在Node.js中同步promises的麻烦

时间:2015-10-02 21:42:20

标签: node.js asynchronous promise sails.js q

我目前正在使用框架Sails.js在Node.JS中执行API。我第一次使用承诺,我有一些麻烦可以像我想的那样同步我的承诺。

我的主要功能如下:

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())只有在收到拒绝或解决后才会被执行。

1 个答案:

答案 0 :(得分:2)

你的思路是正确的。 问题是你正在调用你的函数而不是引用它:

.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中的执行顺序将首先评估它,因为它位于当时的()内。

在promise链中,始终只调用第一个函数。例如:

function first () { /*...*/ } // All return promise.
function second() { /*...*/ }
function third () { /*...*/ }

first() // Invoked
    .then(second) // Not invoked. second() will have been bad here.
    .then(third);