简体   繁体   中英

how to change async callback using promise in nodejs?

I am a beginner and am currently making a User Management system in NodeJS, I had previously done it with MongoDB, Express. Right now im making it all again with Express, Sequelize and Postgresql to better understand some concepts.

What im stuck at is the reset page where I previously used Async.waterfall to get the email id and send email using SendGrid, but now I want to know how can I convert it using Promises..? It is a bit confusing to understand how to use them with concurrent callbacks.

Here is the previous code using the async.waterfall :

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

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

                user.save(function(err) {
                    done(err, token, user);
                });
            });
        },
        //3
        function(token, user, done) {

            var nodemailer = require('nodemailer');
            var sgTransport = require('nodemailer-sendgrid-transport');

            var options = {
                auth: {
                    api_key: ''
                }
            };

            var mailer= nodemailer.createTransport(sgTransport(options));

            var mailOptions = {
                to: user.local.email,
                from: 'passwordreset@demo.com',
                subject: 'Node.js Password Reset',
                text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
                'Please 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'
            };
            mailer.sendMail(mailOptions, function(err) {
                req.flash('forgotMessage', 'An e-mail has been sent to ' + user.local.email + ' with further instructions.');
                done(err, 'done');
            });
        }
    ],
    //2 out of Async
    function(err) {
        if (err) return next(err);
        res.redirect('/forgotpassword');
    });
});

From async.waterfall documentation

Runs an array of functions in series, each passing their results to the next in the array. However, if any of the functions pass an error to the callback, the next function is not executed and the main callback is immediately called with the error.

So its exactly the same job as Promise.then do, just chain your promises.

    crypto.randomBytes(20)
    .then( function (buf) {
         var token = buf.toString('hex');
         return token;
    })
    .then( function(token) {
       return Model.User.findOne({where: {'email' : req.body.email}});
    })
    .then(function (user) {
         if(!user){
            //    throw no user found error             
         }

         return Model.User.create();

    })
    .catch( function(err) { 
       // error handling
       // catch no user found error and show flash message
    });

You have to have single catch in the end of promises chain, and then should not to be inside of another .then function. I can suggest to read this article - We have a problem with promises .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM