【问题标题】:Trouble to synchronise promises in Node.js using Q使用 Q 在 Node.js 中同步 Promise 的麻烦
【发布时间】:2015-12-31 04:49:55
【问题描述】:

我目前正在使用框架 Sails.js 在 Node.JS 中做一个 API。我是第一次使用 Promise,但在同步我的 Promise 时遇到了一些麻烦。

我的主要功能如下:

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

【问题讨论】:

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


    【解决方案1】:

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

    .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 的 () 内。

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

    function first () { /*...*/ } // All return promise.
    function second() { /*...*/ }
    function third () { /*...*/ }
    
    first() // Invoked
        .then(second) // Not invoked. second() will have been bad here.
        .then(third);
    

    【讨论】:

    • 我试过你告诉我的,它有效。非常感谢 !但是,它产生了另一个问题。我希望我的函数 addCreditCardToStripeAccount 采用 2 个参数。我做了一些实验,似乎 deferred.resolve() 只能携带 1 个参数。那是对的吗 ?我是否必须改用对象或数组之类的复合值?
    • 如果您使用的是bluebird,您可以使用数组,并将.then() 替换为.spread()。我不确定本地承诺。我是AFK,但我可以帮上忙。乐意效劳。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2013-06-05
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多