在承诺中有多个异步等待

时间:2018-02-02 16:35:30

标签: javascript node.js async-await es6-promise

不确定我是否正确执行此操作。所以我在我的nodejs脚本中使用async await,我从电子邮件帐户收到电子邮件,并将电子邮件和收件人保存到数据库中。我遇到的问题是收件人未收到的最后一封电子邮件。不知道我在这里做错了什么。这是我的代码。

function saveEmailRecipients(message, pool, emailId){
    return new Promise(function(resolve, reject){
            var saveCC =  async function(){
                 //Store cc
                 if(message.cc != undefined){
                    for (var k in message.cc) {
                        let cc = message.cc[k];

                        var request = pool.request();
                        request.input('email_id', sql.Int, emailId);
                        request.input('email_address', sql.VarChar, cc.address );
                        request.input('email_address_name', sql.VarChar, cc.name);
                        request.input('created_by', sql.VarChar, 'system');
                        request.input('recipient_type', sql.VarChar, 'CC');

                        await request.query('INSERT INTO email_recipient_temp(email_id, email_address, email_address_name, created_by, recipient_type) values (@email_id, @email_address, @email_address_name, @created_by, @recipient_type)');


                    }
                }

                 //Store to
                 if(message.to != undefined){
                    for (var j in message.to) {
                        let to = message.to[j];

                        var request = pool.request();
                        request.input('email_id', sql.Int, emailId);
                        request.input('email_address', sql.VarChar, to.address );
                        request.input('email_address_name', sql.VarChar, to.name);
                        request.input('created_by', sql.VarChar, 'system');
                        request.input('recipient_type', sql.VarChar, 'TO');

                        await request.query('INSERT INTO email_recipient_temp(email_id, email_address, email_address_name, created_by, recipient_type) values (@email_id, @email_address, @email_address_name, @created_by, @recipient_type)');
                    }
                }
            }

            var recipientResults = saveCC();
            recipientResults
            .then(function(){
                resolve();
            })
            .catch(function(err){
                reject(err)
            })
        });  
};

async function main() {
    try
    {
        let pool = (await sql.connect(config));

        var messages = (await getEmailsFromEmailServer());

        for (var messageIndex in messages) {

             //Save email
             var emailId =  (await saveEmail(pool,  messages[messageIndex]));
             (await saveEmailRecipients (messages[messageIndex], pool, emailId));
             //(await saveAttachments(messages[messageIndex], emailId));
        }

        client.quit();
        process.exit();
    }
    catch(err){
        console.log(err);
        client.quit();
        process.exit();
    }
};

main();

我省略了一些功能,所以我们可以专注于saveEmailRecipient。我怀疑我不对的是什么。我有两个循环,每个循环都插入数据库。我知道request.query会返回一个承诺。我不确定是否需要将整个事物包装在另一个异步函数中,或者我应该在这里使用promise.all。

1 个答案:

答案 0 :(得分:1)

我要猜测保存问题的根源在于你使用'process.exit()'而不是正确关闭连接这一事实,遗憾的是这只是一个假设,因为我无法测试你的代码

我可以建议您不要在代码中使用'process.exit'并使用promises或async / await。

注意:它们可以一起使用,只有很多坑,请参阅'Understand promises before you start using async/await' by 'Daniel Brain'了解详情

以下是仅使用承诺的示例:

function addRecipient(pool, type, id, cc) {
    const request = pool.request();

    request.input('email_id', sql.Int, id);
    request.input('email_address', sql.VarChar, cc.address );
    request.input('email_address_name', sql.VarChar, cc.name);
    request.input('created_by', sql.VarChar, 'system');
    request.input('recipient_type', sql.VarChar, type);

    // Return the query's promise.
    return request.query(`
        INSERT INTO email_recipient_temp (
            email_id,
            email_address,
            email_address_name,
            created_by,
            recipient_type
        ) values (
            @email_id,
            @email_address,
            @email_address_name,
            @created_by,
            @recipient_type
        )
    `);
}
function saveEmailRecipients (message, pool, emailId) {
    // The arrays of promises
    const promises = [];

    // Process the 'TO's
    if(message.to != undefined){
        for (const to of message.to) {
            // Add the promise to the promise array
            promises.push(addRecipient(
                pool,
                'TO',
                emailId,
                to
            ));
        }
    }

    // Process the 'CC's
    if(message.cc != undefined){
        for (const cc of message.cc) {
            // Add the promise to the promise array
            promises.push(addRecipient(
                pool,
                'CC',
                emailId,
                cc
            ));
        }
    }

    // return a promise of promises
    return Promise.all(promises);
}

sql.connect(config)
.then(pool => {
    // Retrieve the messages
    getEmailsFromEmailServer()

    // Convert all the messages into promises
    .then(messages => Promise.all(
        // For each of the messages
        messages.map(message => 

            // Save the email
            saveEmail(pool, message)

            // Now use the emailId (returns a promise)
            .then(emailId => saveEmailRecipients(
                message,
                pool,
                emailId
            ))
        )
    ))

    .catch(err => {
        // There was an error.
        console.error(err);
    })

    // This is run regardless of the promise outcome
    .finally(() => {
        // Tidy up.
        client.quit();
        pool.close();
    });

})

请注意,我不能说这会立即起作用,因为我不得不做出一些假设,并且无法访问数据库,但是,我希望它有所帮助。