2017-04-24 10 views
0

私は初心者で、現在NodeJSでUser Managementシステムを作っています。以前はMongoDB、Expressでそれをやっていました。今、Express、Sequelize、Postgresqlでいくつかの概念をよりよく理解するために、すべてを再作成しています。nodejsで約束を使って非同期コールバックを変更する方法は?

私が以前にAsync.waterfallを使用して電子メールIDを取得し、SendGridを使用して電子メールを送信したリセットページがありましたが、どのように私が約束を使用して変換することができるか知りたいですか?同時コールバックでそれらを使用する方法を理解するのはちょっと混乱します。ここ

はasync.waterfallを使用して、以前のコードである: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: 'p[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の結果を要求し、function3はfunction2の結果を必要とします。 promise.all execは同時に約束し、promiseArr内の各関数は別のexecに依存することはできません。 – styopdev

答えて

2

は、それぞれの次 にその結果を渡し、一連の関数の配列を実行します配列。ただし、いずれかの関数がエラー をコールバックに渡すと、次の関数は実行されず、メインの コールバックがすぐにエラーとともに呼び出されます。

プロミスとまったく同じ仕事ですので、約束してください。

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

.catchの前に新しい.then呼び出しを追加し、その中にreturn transport.sendMail(options)を使用してください。 – styopdev

+0

大丈夫@styopdevですが、なぜ私たちはそれらを分けるのですか?なぜなら、.then関数の中で.then関数を使うと、それはうまく動作しないからです。 findOneメソッドと作成を別々にしたのはなぜですか? –

関連する問題