【问题标题】:async.series() continues to execute next functions despite errors尽管出现错误,async.series() 仍继续执行下一个函数
【发布时间】:2014-05-03 13:34:33
【问题描述】:

我正在使用来自 caolan 的 async 模块的 async.series() 控制流。 ü 就像文档的解释一样,它应该依次执行所有函数,一个接一个地执行,并在一个错误调用其回调时停止;如果其中一个函数出错,我的实际上会调用主回调,但随后会愉快地继续按顺序执行其余函数。

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(); 然后继续,甚至将用户保存在数据库中。显然这不是预期的结果。

有人知道我在这里做错了什么吗?

【问题讨论】:

    标签: node.js express async.js keystonejs


    【解决方案1】:

    如果您想停止当前函数的执行,仅调用回调是不够的。例如:

    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
        // ...
    }
    

    【讨论】:

    • OP 也可以将else 用于相同目的
    • 是的@soulcheck,我编辑了帖子以显示它也作为示例。
    • 在我的示例中,将所有 cb(true) 和 cb(null) 更改为返回 cb(...) 会在引发错误后停止执行更多函数。但是,在第二次调用此函数后,它仍然会在出错后停止进一步执行函数,但 async 现在会抛出以下错误:
    • 在我的示例中,将所有 cb(true) 和 cb(null) 更改为返回 cb(...) 会在引发错误后停止执行更多函数。但是,在第二次调用此函数后,它仍然会在出现错误后停止进一步执行函数,但 async 现在会抛出以下错误:错误:已调用回调。
    • 第二次怎么称呼它? Async.js 有一个系统可以防止您创建执行多次的回调,请参阅github.com/caolan/async/blob/master/lib/async.js,第 19 行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    相关资源
    最近更新 更多