Search code examples
node.jsasync-awaites6-promisemysql2

Nodejs with mysql2, promise functions in are not excuted in order


In my nodejs app I need to write data into my mysql database, then create a PDF file out of this data and then send this file as an attachment in an email.

The two functions generatePDF() and sendMail() are async function and, therefore, return a promise. I am calling these two functions in connection.query(). I know that I have to use promises in order to run generatePDF() first before sendMail() is executed but I am unable to get this working.

I tried to use, without success :

  • await generatePDF() and await sendMail() (with and without async before function) but this throws an error SyntaxError: await is only valid in async functions and the top level bodies of modules
  • generatePDF().then(sendMail()) but they are executed asynchronously
  • Promise.all([generatePDF(),(sendMail()]) but they are executed asynchronouslyi

For clarity, I only post parts of the code.

const mysql = require('mysql2'); // I tried mysql2/promise as well


app.post('/HSF/calculator/register', async function (request, response) {
    var params = request.body;
    //console.log('params:',params);
    connection.query('INSERT INTO client_data SET ?', params, function (error, results, fields) {
        if (error) {
            throw error;
        }
        else {
                console.log('after .query(), before createOutputFile')
                var createOutputFile = `
                        SELECT
                                CONCAT("{",'"id":',
                                         JSON_OBJECT(
                                         "clientID",clientID,"name",name,"email",email,"age",age,"currentWeight",currentWeight,"weightUnit",weightUnit,"goalWeight",goalWeight,
                                         "height",height,"goalDate",goalDate,"mealsPerDay",mealsPerDay,"activityLevel",activityLevel,"eatingStyle",eatingStyle,"nutritionalRatio",
                                         nutritionalRatio,"workoutLevel",workoutLevel)
                                ,"}")
                                AS json FROM HerSoulFit.client_data
                                WHERE fileCounter = ${params.fileCounter}
                                INTO OUTFILE '/var/lib/mysql-files/data_${params.fileCounter}.json';`
                        connection.query(createOutputFile, (error, results) => {
                                if (error) {
                                        throw error
                                }
                                else {
                                        response.end(JSON.stringify(results));
                                }
                        })
                        await PDF.generatePDF(params.fileCounter)
                        await nodemailer.sendMail(params.name, params.email, params.fileCounter)
                        // does not work: PDF.generatePDF(params.fileCounter).then(nodemailer.sendMail(params.name, params.email, params.fileCounter))

       });
});

```

 

Solution

  • the async keyword is in the wrong place. Remove it and change this line :

    connection.query('INSERT INTO client_data SET ?', params, function (error, results, fields) {
    

    to

    connection.query('INSERT INTO client_data SET ?', params, async function (error, results, fields) {
    

    I confirm it will be better to call sendMail when generatePDF resolve