yanman1234
yanman1234

Reputation: 1019

Node MySql Callback for Multiple Queries

I ran into an issue whilst attempting to create the logic to add rows to a new table I made on my MySql database. When adding a row I need to query the database 4 times to check other rows and to then add the correct value to the new row. I am using node.js and the mysql module to accomplish this. While coding I ran into a snag, the code does not wait for the 4 queries to finish before inserting the new row, this then gives the values being found a value of 0 every time. After some research I realize a callback function would be in order, looking something like this:

var n = 0;
connection.query("select...", function(err, rows){
    if(err) throw err;
    else{
        if(rows.length === 1) ++n;
    }
    callback();
});

function callback(){
    connection.query("insert...", function(err){
         if(err) throw err;
    });
}

Note: The select queries can only return one item so the if condition should not effect this issue.

A callback function with only one query to wait on is clear to me, but I become a bit lost for multiple queries to wait on. The only idea that I had would be to create another variable that increments before the callback is called, and is then passed in the callback function's arguments. Then inside the callback the query could be encapsulated by an if statement with a condition of this being the variable equaling the number of queries that need to be called, 4 for my purposes here. I could see this working but wasn't sure if this sort of situation already has a built in solution or if there are other, better, solutions already developed.

Upvotes: 2

Views: 4358

Answers (2)

Gepser Hoil
Gepser Hoil

Reputation: 4226

You need async (https://github.com/caolan/async). You can do a very complex logic with this module.

var data = {} //You can do this in many ways but one way is defining a global object so you can add things to this object and every function can see it

firstQueryFunction(callback){
    //do your stuff with mysql
    data.stuff = rows[0].stuff; //you can store stuff inside your data object
    callback(null); 
}

secondQueryFunction(callback){
    //do your stuff with mysql
    callback(null);
}

thirdQueryFunction(callback){
    //do your stuff with mysql
    callback(null);
}

fourthQueryFunction(callback){
    //do your stuff with mysql
    callback(null);
}

//This functions will be executed at the same time
async.parallel([
    firstQueryFunction,
    secondQueryFunction,
    thirdQueryFunction,
    fourthQueryFunction
], function (err, result) {
     //This code will be executed after all previous queries are done (the order doesn't matter).
     //For example you can do another query that depends of the result of all the previous queries.
});

Upvotes: 5

Sean
Sean

Reputation: 621

As per Gesper's answer I'd recommend the async library, however, I would probably recommend running in parallel (unless the result of the 1st query is used as input to the 2nd query).

var async = require('async');

function runQueries(param1, param2, callback) {

    async.parallel([query1, query2, query3(param1, param2), query4],
        function(err, results) {
            if(err) {
                callback(err);
                return;
            }

            var combinedResult = {};
            for(var i = 0; i < results.length; i++) {
                combinedResult.query1 = combinedResult.query1 || result[i].query1;
                combinedResult.query2 = combinedResult.query2 || result[i].query2;
                combinedResult.query3 = combinedResult.query3 || result[i].query3;
                combinedResult.query4 = combinedResult.query4 || result[i].query4;
            }
            callback(null, combinedResult);
        });
}


function query1(callback) {
    dataResource.Query(function(err, result) {
        var interimResult = {};
        interimResult.query1 = result;
        callback(null, interimResult);
    });
}

function query2(callback) {
    dataResource.Query(function(err, result) {
        var interimResult = {};
        interimResult.query2 = result;
        callback(null, interimResult);
    });
}

function query3(param1, param2) {
    return function(callback) {
        dataResource.Query(param1, param2, function(err, result) {
            var interimResult = {};
            interimResult.query3 = result;
            callback(null, interimResult);
        });
    }
}

function query4(callback) {
    dataResource.Query(function(err, result) {
        var interimResult = {};
        interimResult.query4 = result;
        callback(null, interimResult);
    });
}

Query3 shows the use of parameters being 'passed through' to the query function.

I'm sure someone can show me a much better way of combining the result, but that is the best I have come up with so far. The reason for the use of the interim object, is that the "results" parameter passed to your callback is an array of results, and it can be difficult to determine which result is for which query.

Good luck.

Upvotes: 2

Related Questions