Nadir
Nadir

Reputation: 97

Nodejs Async await not waiting properly despite of being in correct syntax

I know you might mark it as duplicate or downvote it. but I am unable to figure out a solution despite searching over forums and google. I am basically trying to create a migration system for MySQL nodejs. Code:

const table = require('../orm/Migration');
module.exports = {
   async up(connection) {
       table.newTable()
       table.name('user_sessions')
       console.log("SENT TABLE NAME")
        table.id()
        table.string('username').nullable()
        table.string('ip').nullable()
      table.boolean('success').default(true)
      table.timestamps()
       console.log("Finalizing")
     var d=await table.finalize()
       console.log("after sending finalization")
        return d
   }
}

Migration.js


       if (connected) {
            try{
               var c= await  connection.query(sql_query)
                console.log("Created table. "+this.table_name + JSON.stringify(c))
            }
            catch(ex)
            {
                console.log(ex)
            }
        }
        else
        {
            throw("Not connected to database.")
        }

Main trigger function

var mysql= require('mysql2/promise');
require('dotenv').config()
const fs = require('fs'); 
const { connect } = require('tls');
var path = require('path');
(async () => {
    try{
        var connected=true
        console.log("Connecting to database")
        try{
            var connection =await mysql.createConnection({
                host     : process.env.DB_HOST,
                user     : process.env.DB_USERNAME,
                password : process.env.DB_PASSWORD,
                database : process.env.DB_NAME
            });
            // connection.connect();
            console.log("Connected")
        }
        catch(exce)
        {
            console.log(exce)
            connected=false
        }
        if(connected)
        {
            var dirname = "migrations"
            console.log("\nMigrating");
            var rootpath=path.resolve(__dirname + "/migrations")
            fs.readdirSync(rootpath).forEach(function (dirContent) {
                var fclass=dirContent
                var fc=dirContent.replace(".js","")
                const fname = rootpath+"/" + fc;
                const migration = require(fname);
                (async () => {
                    try{
                        console.log("Before Up call of:" + fc)
                        const upcall =await migration.up(connection);
                        console.log("Upcall returned from " + fc + upcall)
                        console.log("After upcall of :"+ fc)
                    }
                    catch(exc)
                    {
                        console.log(exc)
                    }
                    console.log("Migrating done")
                })()
            })

            //  process.exit(0)
        }
        else
        {
            console.log("Not connected to database")
            // process.exit(0)
        }
    }
    catch(exc)
    {
        console.log(exc)
    }
})()

Console output

Connecting to database
Connected

Migrating
Before Up call of:sessions
Setting Table_name to:user_sessions
SENT TABLE NAME
Finalizing
Before Up call of:users
Setting Table_name to:users
Before Up call of:users2
Setting Table_name to:sessions
Created table. sessions[{"fieldCount":0,"affectedRows":0,"insertId":0,"info":"","serverStatus":2,"warningStatus":1},null]
after sending finalization
Upcall returned from sessionstrue
After upcall of :sessions
Migrating done
Created table. sessions[{"fieldCount":0,"affectedRows":0,"insertId":0,"info":"","serverStatus":2,"warningStatus":1},null]
after await . true
Upcall returned from users2true
After upcall of :users2
Migrating done
Created table. sessions[{"fieldCount":0,"affectedRows":0,"insertId":0,"info":"","serverStatus":2,"warningStatus":1},null]
Upcall returned from userstrue
After upcall of :users
Migrating done

I don`t know why async await is behaving this way. I am expecting something like

Before Up call of:users
Setting Table_name to:users 
Created table. users[{"fieldCount":0,"affectedRows":0,"insertId":0,"info":"","serverStatus":2,"warningStatus":1},null]
after sending finalization
Upcall returned from users

because that's the correct order of execution. As all functions are async and every call is put in await. whats wrong with nodejs

Nodejs Version v14.15.3

Upvotes: 0

Views: 107

Answers (1)

Eduard Hasanaj
Eduard Hasanaj

Reputation: 895

The problem is that you are using forEach to iterate over migrations in main trigger function. Of course the forEach cannot be awaited from the outer async function. Here it is my suggestion(not tested)

async function migrate() {
    var rootpath = ath.resolve(__dirname + "/migrations")
    const migrationFilePaths = fs.readdirSync(rootpath);

    for (const migrationPath of migrationFilePaths) {
        let fc = migrationPath.replace(".js","")
        const fname = rootpath +"/" + fc;
        const migration = require(fname);
        try {
            await migration.up(connection);
        }
        catch(err) {
            
        }
    }
}

The await in for will be awaited by the migrate function.

Upvotes: 2

Related Questions