Jabaa
Jabaa

Reputation: 1753

Node js: Express js asynchronous db query execution-return results got undefiend

Just started to learn express js framework ,here is my simple database query execution part its invoked with this url localhost:3000/api/test.

db.query('SELECT * FROM user', function (error, results, fields) {
            if (error) throw error;
            console.log('The result is:', results[0].id);

            return results;
        });

Does it really asynchronous?? suppose another user request this url does he need to wait for the previous query execution??.

I've heard about async package ,but don't know how this is applicable in my case

UPDATE

I got proper result in console.log(); but when i return the result i got undefined error

Here is my model.js

module.exports = {
    getUser:function () {
        db.query('SELECT * FROM user', function (error, results, fields) {
            if (error) throw error;
            console.log('The result is: ', results[0].id);

        });

    }

}

From my controller.js

var model = require('../models/user.js');
module.exports = {
    getData : function(req, res){
        //invoke model
        console.log(model.getUser());

    }
}

Upvotes: 2

Views: 2352

Answers (2)

Kulvar
Kulvar

Reputation: 1179

When you deal with callback, the safe and clean way to handle them is Promises. It's now standard in JavaScript and don't require any module.

And yes it is asynchronous. Behind, there'll be network access and dialogs with the database server. Only when they're done chatting will the callback be called.

module.exports = {
    getUser: function () {
        // wrap asynchronously called callback in Promise
        new Promise((resolve, reject) => {
            db.query("SELECT * FROM user", (error, results, fields) => {
                if (error) {
                    reject(error); // similar to "throw"
                }
                else {
                    resolve({ results, fields }); // similar to "return"
                }
            });
        });
    }
};

How do you use it:

Vanilla notation:

// similar to "try"
model.getUser()
.then((answer) => {
    console.log("answer", answer);
})
// similar to "catch"
.catch((error) => {
    console.log("error", error);
});

async-await notation (only available in last versions of nodejs & browsers):

// you must be in an async environement to use "await"
async function wrapper() {
    try {
        var answer = await model.getUser(); // wait for Promise resolution
        console.log("answer", answer);
    }
    catch(error) {
        console.log("error", error);
    }
}
// async function return automatically a Promise so you can chain them easily
wrapper();

Upvotes: 0

AO_
AO_

Reputation: 2874

Node is non-blocking and will serve this request as and when it's called.

If another user hits this endpoint then it will execute again regardless if the first query has completed or not (unless the SQL has locked the table, in which case all consecutive connections/queries will wait and may timeout because of it). This happens on a connection basis.

You should make sure to check your SQL server (MySQL?) configs here to make sure there are enough max_connections to be able to cope with whatever load you are expecting.

Remember that the biggest bottleneck to an application is usually the database.


Your query above will need a callback to return the data asynchronously.

db.query('SELECT * FROM user', function (error, results, fields) {
    if (error) throw error;
    console.log('The result is:', results[0].id);

    //cb=callback function passed in to context
    if (cb) cb(results);
});

Updated answer from updated question

In your model.js:

module.exports = {
    getUser:function (cb) {
        db.query('SELECT * FROM user', function (error, results, fields) {
            if (error) throw error;
            console.log('The result is: ', results[0].id);
            if (cb) cb(results);

        });

    }

}

In your controller.js:

module.exports = {
    getData : function(req, res){
        //invoke model

        model.getUser(function(results) {
            console.log(results);
        });

    }
}

Upvotes: 3

Related Questions