Паспорт. js - как использовать рендеринг электронной почты асинхронно - PullRequest
0 голосов
/ 02 апреля 2020

Я использую Express с Sequelize / MariaDB и Passport. js для аутентификации пользователя.

Я нахожусь в части регистрации (которая работает), но я не могу отобразить и вернуть электронное письмо с просьбой подтвердить свою электронную почту.

passport.js (содержит стратегии аутентификации)

passport.use('user-signup-email', new LocalStrategy({
    //Process/validate input, check database for existing emails, create user, add to database...

    ...
    if (newUser) {
        var token = jwt.sign( { data: newUser.id }, newUser.login_pass + "-" + newUser.account_created);
        var URLdata = { 
            id:                newUser.id,
            expiration_time:   Date.now() + 86400000,   //24 hours
            url:               token,
            email_info:        mail.createActivationEmail(req.app, newUser.login_key, newUser.user_alias, token)                        
        };

        console.log("info: " + URLdata.email_info);

        ... 
            //Store dynamic URL and email contents (in case of resending) in database with expiration time
            //And then send the email that was just rendered
    }

mail.js

exports.createActivationEmail = (app, recipientAddress, userName, url) => {
    app.render('emails/activation_email', {    
        layout: false,
        page_title: 'Please confirm your account!',
        dynamic_url: url
    }, function(err, rendered) {
        if (err) {
            console.log("Q [" + err + "]");
        }

        console.log("R " + rendered.toString());
        return {  
            from:       adminEmailAddress,
            to:         recipientAddress,
            cc:         false,
            bcc:        false,
            subject:    'Welcome to example.com ' + userName + '!',
            html:       rendered.toString(),
            text:       "TO DO" 
        };
    });
};

Последний console.log в passport.js отображается «информация: не определено». Но если я распечатаю вывод в модуле mail.js перед возвратом, это нормально.

Я предполагаю, что это асинхронная проблема c? Как мне это исправить?
Мне все еще немного неясно, какие обещания и асиновые блоки c ожидают в этом контексте.

Заранее благодарен за любую помощь, которую вы можете предложить!

1 Ответ

1 голос
/ 02 апреля 2020

Вы неправильно поняли функции обратного вызова. Обратные вызовы (должны, когда вы их пишете) асинхронны: https://nemethgergely.com/async-function-best-practices/ Как писать асинхронные функции для Node.js

Я изменил вашу createActivationEmail функцию. Последний аргумент теперь является обратным вызовом, который вызывается, когда ваш код app.redner готов.

passport.use('user-signup-email', new LocalStrategy({
    //Process/validate input, check database for existing emails, create user, add to database...

    // ...
    if(newUser) {

        var token = jwt.sign({ data: newUser.id }, newUser.login_pass + "-" + newUser.account_created);
        mail.createActivationEmail(req.app, newUser.login_key, newUser.user_alias, token, (err, email_info) => {



            var URLdata = {
                id: newUser.id,
                expiration_time: Date.now() + 86400000,   //24 hours
                url: token,
                email_info
            };


            console.log("info: " + URLdata.email_info);

            //... 
            //Store dynamic URL and email contents (in case of resending) in database with expiration time
            //And then send the email that was just rendered


        });

    }

}));

exports.createActivationEmail = (app, recipientAddress, userName, url, done) => {
    app.render('emails/activation_email', {    
        layout: false,
        page_title: 'Please confirm your account!',
        dynamic_url: url
    }, function(err, rendered) {

        if (err) {
            console.log("Q [" + err + "]");
            cb(err);
            return;
        }

        console.log("R " + rendered.toString());
        
        done(null, {  
            from:       adminEmailAddress,
            to:         recipientAddress,
            cc:         false,
            bcc:        false,
            subject:    'Welcome to example.com ' + userName + '!',
            html:       rendered.toString(),
            text:       "TO DO" 
        });

    });
};
...