0

How to wait for data before run the next execution in node.js. For example, I have 3 parts need to be executed. Collect data from job table, collect data from vehicle table then run my jar file. So the current output of console is 0->1->3->5->7->2->4->6. How to make it like 0->1->3->2->4->5->6->7 . I want to wait for data from first and second query then run the jar file.

var express = require('express');
var router = express.Router();

router.post('/', function(req, res, next) {
    //console.log("pending data");

    console.log("0");

    var date = req.param('date');
    var joblist;
    var vehiclelist;

    console.log("1");

    res.locals.connection.query('SELECT * FROM job WHERE date = ?',[date] , function (error, results, fields) {
        console.log("2");
        if (error) throw error;
        joblist = JSON.stringify(results);
    });

    console.log("3");

    res.locals.connection.query('SELECT * FROM vehicle ' , function (error, results, fields) {
        console.log("4");
        if (error) throw error;
        vehiclelist = JSON.stringify(results);
    });

    console.log("5");

    var exec = require('child_process').exec, child;
child = exec('java -jar /home/java/testinput.jar',
  function (error, stdout, stderr){
    //console.log('stdout: ' + JSON.stringify(stdout));
    //console.log('stderr: ' + stderr);
    console.log("6");
    res.send(joblist+"  "+stderr);
    if(error !== null){
      console.log('exec error: ' + error);
    }
});
console.log("7");

});

module.exports = router;
phoon
  • 369
  • 1
  • 6
  • 21

1 Answers1

2

The issue is that the following:

function (error, results, fields) {
    console.log("2");
    if (error) throw error;
    joblist = JSON.stringify(results);
}

is a callback function. You're passing that function in your query() call, and telling it to execute the function when it's finished executing the query. As soon as your code has requested that query (not executed it), it immediately goes on to execute the next code.

In earlier days, the solution to this would be to define all later actions inside that callback function, as roughly such:

var express = require('express');
var router = express.Router();

router.post('/', function(req, res, next) {
    //console.log("pending data");

    console.log("0");

    var date = req.param('date');
    var joblist;
    var vehiclelist;

    console.log("1");

    res.locals.connection.query('SELECT * FROM job WHERE date = ?',[date] , function (error, results, fields) {
        console.log("2");
        if (error) throw error;
        joblist = JSON.stringify(results);

        console.log("3");

        res.locals.connection.query('SELECT * FROM vehicle ' , function (error, results, fields) {
            console.log("4");
            if (error) throw error;
            vehiclelist = JSON.stringify(results);

            console.log("5");

            // etc

            res.send('blah')
        });

    });

});

module.exports = router;

Modern JS now has promises, and async/await, which are generally accepted as nicer replacements for callbacks in asynchronous code: https://javascript.info/async-await

Quick snippet as per follow-up comment: (It's not fully working code, just an example of the concepts)

var express = require('express');
var router = express.Router();

router.post('/', async function(req, res, next) {
    //console.log("pending data");

    console.log("0");

    var date = req.param('date');
    var joblist;
    var vehiclelist;

    console.log("1");

    var promises = [];
    promises.push(query1(date));
    promises.push(query2());

    var results = await Promise.all(promises);
    console.log(results[0]); // query1
    console.log(results[1]); // query2

    res.send('blah');
});

function query1(date) {
    return new Promise((resolve, reject) => {
        res.locals.connection.query('SELECT * FROM job WHERE date = ?',[date] , function (error, results, fields) {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
        }
    })
}

function query2() {
    return new Promise((resolve, reject) => {
        res.locals.connection.query('SELECT * FROM vehicle ' , function (error, results, fields) {
            if (error) {
                reject(error);
            } else {
                resolve(results);
            }
        }
    })
}

module.exports = router;
jameslol
  • 1,829
  • 16
  • 18
  • For your solution is like I have to wait for first query then run second query then run my execution, but what I need is run first and second query at same time then run execution of jar file when first and second query data is return – phoon Apr 30 '19 at 03:01
  • This is where you'll need to use promises. Encapsulate all your database queries inside promise-returning functions, put them in an array of promises, and then run `var results = await Promise.all(array);` – jameslol Apr 30 '19 at 03:10
  • I added a snippet for this. But this is incorporating quite a lot of concepts. You're going to have to read up on callbacks, promises, async/await, and specifically Promise.all(). Until you're comfortable with all of those, I'd probably think about just how much you need to get both of those calls in parallel. – jameslol Apr 30 '19 at 03:15