回调如何在带有异步瀑布的Javascript中工作

时间:2016-01-19 19:46:00

标签: javascript node.js

我目前正在编写一个从node.js应用程序实现密码重置的教程,并且我需要使用库异步来清理代码,使其成为回调混乱。我对Javascript相对较新,而且来自Java和Objective-C等更强类型的语言,我遇到了解决语言固有的自由问题。

无论如何,我理解每个前面的函数实际上是如何通过回调将值传递给下一个函数,但是我在每次回调唤醒开始时都无法理解“err”参数的要点。例如,在第一个函数中,引发的回调被完成(错误,令牌),但是下一个函数将令牌作为其第一个参数而不是错误。我正在努力弄清楚下一个函数如何获取该标记参数,并在“err”参数是回调中列出的参数时使用它。我可能会误解这个概念或遗漏一些东西,所以任何帮助都会受到赞赏。

app.post('/forgot', function (req, res, next) {
    async.waterfall([function (done) {
        crypto.randomBytes(20, function (err, buf) {
            var token = buf.toString('hex');
            done(err, token);
        });
    },
        function (token, done) {
            User.findOne({ email: req.body.email }, function (err, user) {
                if (!user) {
                    return { error : 'No account with that email address exists'};
                }

                user.resetPasswordToken = token;
                user.resetPasswordExpires = Date.now() + 3600000; //1 hour

                user.save(function (err) {
                    done(err, token, user);
                });
            });
        },
        function (token, user, done) {
            var smtpTransport = nodemailer.createTransport('SMTP', {
                service: 'SendGrid',
                auth : {
                    user: "swagboi",
                    pass: "woo"
                }
            });
            var mailOptions = {
                to: user.email,
                from: 'passwordreset@demo.com',
                text: 'You are receiving this because you (or someone else) have requested hte reset of the password for your account. \n\n' +
                    'Pleaes click on the following link, or paste this into your browser to complete the process: \n\n' +
                    'http://' + req.headers.host + '/reset/' + token + '\n\n' +
                    'If you did not request this, please ignore this email and your password will remain unchanged. \n'
            };
            smtpTransport.sendMail(mailOptions, function (err) {
                done(err, 'done');
            });
        }
    ], function (err) {
        if (err) return next(err);
    })
});

1 个答案:

答案 0 :(得分:2)

如果仔细观察,您会看到async.waterfall接受两个参数:任务列表和回调。

done不仅仅是列表中的下一个任务。这是async.waterfall知道如何进行的一些特定功能。把它想象成

function done(err, result) {
  if (err) {
    callback(err);
  } else {
    tasks[i++](result, done);
  }
}

(如果done仅接受两个参数)

即。只有结果传递给列表中的下一个任务。如果传递错误,则会调用回调。

Relevant source code(这可能不容易理解)。