async.series()继续执行下一个函数,尽管有错误

时间:2014-03-25 15:29:09

标签: node.js express async.js keystonejs

我正在使用来自caolan异步模块的async.series()控制流。 ü 不像doc的解释那样它应该按顺序执行所有函数,一个接一个地执行,当一个函数调用带有错误的回调时停止;如果其中一个函数获得了错误,那么我实际上调用了主回调,然后很高兴继续按顺序执行其余的函数。

async.series([

    function (cb) {

        if (!req.body.join_firstname || !req.body.join_lastname || !req.body.join_email || !req.body.join_password) {
            req.flash('error', 'Please enter a name, email and password.');
            cb(true);
        }

        if (req.body.join_password !== req.body.join_passwordConfirm) {
            req.flash('error', 'Passwords must match.');
            cb(true);
        }

        if (req.body.join_email !== req.body.join_emailConfirm) {
            req.flash('error', 'Emails must match.');
            cb(true);
        }

        cb(null);

    },

    function (cb) {

        keystone.list('User').model.findOne({
            email: req.body.join_email
        }, function (err, user) {

            if (err || user) {
                req.flash('error', 'User already exists with that email address.');
                cb(true);
            }

            cb(null);

        });

    },

    function (cb) {

        var userData = {
            name: {
                first: req.body.join_firstname,
                last: req.body.join_lastname
            },
            email: req.body.join_email,
            password: req.body.join_password
        };

        var User = keystone.list('User').model,
            newUser = new User(userData);

        newUser.save(function (err) {
            if (err) {
                //if there's an error, don't send activation mail
                cb(err);
            } else {
                newUser.activationEmail(function (err) {
                    if (err) {
                        //if we can't send activation email,
                        //delete user from db to prevent re-registration failing because of non-unique email
                        keystone.list('User').model.findOne({
                            email: req.body.join_email
                        }).remove(function (err) {
                            req.flash('error', "Couldn't send an activation email. Contact support if this problem persists.");
                            cb(true);
                        });
                    } else {
                        cb(err);
                    }
                });
            }
        });
    }
], function (err) {
    if (err) return next();
    req.flash('success', "Hi, " + req.body.join_firstname + "! We've sent you an activation email. Please check your inbox and spam folder.");
    return res.redirect('/');
});

例如,当我故意输入错误的密码确认值时,它会抛出错误,执行回调和return next();,然后继续,甚至将用户保存在数据库中。显然这不是预期的结果。

任何人都知道我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

如果要停止执行当前函数,则不足以调用回调。例如:

function(cb) {

    if (!req.body.join_firstname || !req.body.join_lastname || !req.body.join_email || !req.body.join_password) {
        req.flash('error', 'Please enter a name, email and password.');
        cb(true);  // will add this callback to the stack
    }
    // continuing here
    // ...
}

要么改变你的if-then-construct:

function(cb) {

    if (!req.body.join_firstname || !req.body.join_lastname || !req.body.join_email || !req.body.join_password) {
        req.flash('error', 'Please enter a name, email and password.');
        cb(true);  // will add this callback to the stack
    } else if (req.body.join_password !== req.body.join_passwordConfirm) {
        //...
    }
    // no more code here
}

或返回:

function(cb) {

    if (!req.body.join_firstname || !req.body.join_lastname || !req.body.join_email || !req.body.join_password) {
        req.flash('error', 'Please enter a name, email and password.');
        return cb(true);  // will add this callback to the stack and return
    }
    // will only be executed if the if is false
    // ...
}