2017-04-24 42 views
0

我是一名初學者,目前正在NodeJS中製作用戶管理系統,之前我曾在MongoDB,Express上做過。現在,我再次用Express,Sequelize和Postgresql來完成一些概念。如何使用nodejs中的promise來更改異步回調?

什麼我堅持是重置頁面,我以前使用Async.waterfall獲得電子郵件ID和使用SendGrid發送電子郵件,但現在我想知道如何使用Promises將其轉換..?瞭解如何在併發回調中使用它們有點困惑。

下面是使用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: '[email protected]', 
       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'); 
    }); 
}); 
+0

你可以使用Promise.all([]) –

+0

@UditKumawat如何像我的結構是什麼?我甚至感到困惑,如果即時通訊使用諾言,我甚至不得不使用done()?你能用例子來解釋嗎?會有很多幫助 –

+0

@UditKumawat不,他不能,因爲function2需要function1的結果,function2的結果等等。 Promise.all execs同時承諾,promiseArr中的每個函數都不能依賴於另一個函數。 – styopdev

回答

2

從async.waterfall文檔

運行的功能串聯陣列,每個傳遞它們的結果到 在下一陣列。但是,如果任何函數將錯誤 傳遞給回調,則不會執行下一個函數,並立即調用主要的 回調並返回錯誤。

所以它和Promise完全一樣的工作。然後,只是鏈接你的承諾。

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 
    }); 

你必須在承諾鏈的末端單catch,並then不應該成爲另一個.then函數中。我可以建議閱讀這篇文章 - We have a problem with promises

+0

我應該如何包含nodemailer部分?!我應該將它創建爲不同的函數,然後通過名稱將該函數調用到.then鏈中? –

+0

添加新的.then呼叫之前.catch和使用return transport.sendMail(選項)裏面它 – styopdev

+0

好的@styopdev,但我可以問爲什麼我們將它們分開?是因爲如果我們在.then函數中使用.then函數,它不會工作。這就是爲什麼你分離findOne方法和創建? –