Soy principiante y actualmente estoy haciendo un sistema de Gestión de Usuarios en NodeJS, anteriormente lo había hecho con MongoDB, Express. En este momento estoy haciendo todo de nuevo con Express, Sequelize y Postgresql para comprender mejor algunos conceptos.
En lo que estoy atascado es en la página de reinicio donde anteriormente usé Async.waterfall para obtener la identificación del correo electrónico y enviar correos electrónicos usando SendGrid, pero ahora quiero saber cómo puedo convertirlo usando Promises... Es un poco confuso entender cómo usarlos con devoluciones de llamada simultáneas.
Aquí está el código anterior usando 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'); }); });De la documentación de async.waterfall
Ejecuta una matriz de funciones en serie, cada una de las cuales pasa sus resultados a la siguiente en la matriz. Sin embargo, si alguna de las funciones pasa un error a la devolución de llamada, la siguiente función no se ejecuta y la devolución de llamada principal se llama inmediatamente con el error.
Así que es exactamente el mismo trabajo que Promise. Entonces hazlo, simplemente encadena tus promesas.
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 }); Debe tener una sola catch al final de la cadena de promesas, y then no debe estar dentro de otra función .then . Puedo sugerir leer este artículo - Tenemos un problema con las promesas .