0

While debugging the code I noticed that the line 4 is getting skipped and then processed after line 5 & 6.

1 router.post(routes.availability, function (req, res) {
2    const sqlClient = require('../framework/db/mysql');
3    var query = "Select 1 as 'data' from dual;";
4    var result = sqlClient.execute(query);
5    res.send(toString(result));
6    res.end();
7 })

The below gets executed at line 4.

execute(sql) {
    this.db.query(sql, function (err, results) {
        if (err) {
            logger.log("error", err);
            return null;
        }

        if (results.length)
            return results;
        return null;
    });
}

Can someone please explain why and provide a solution?

  • Have a look here: https://stackoverflow.com/questions/29555290/what-is-the-difference-between-res-end-and-res-send. `.send()`, and `.end()` are not needed together. – Adrian Roworth Nov 15 '19 at 16:40
  • Read and study this: [How to return an asynchronous value](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323). Your `execute()` function never returns anything. Returning from inside an asynchronous callback only returns to the callback, not to the calling function. And, the calling function has already returned when your callback is called (e.g. your callback is called AFTER the calling function has already returned). – jfriend00 Nov 15 '19 at 17:01

2 Answers2

1

this.db.query is a async function, you should await until it completed

1 router.post(routes.availability, async function (req, res) {
2    const sqlClient = require('../framework/db/mysql');
3    var query = "Select 1 as 'data' from dual;";
4    var result = await sqlClient.execute(query);
5    res.send(toString(result));
6    res.end();
7 })


async function execute(sql) {
    return await this.db.query(sql, function (err, results) {
        if (err) {
            logger.log("error", err);
            return null;
        }

        if (results.length)
            return results;
        return null;
    });
}

You can use this

Xander Le
  • 44
  • 5
  • This seems unlikely to be correct. I don't know of any DB interfaces that both return a promise (that you could use with `await`) AND accept a callback. It will be one or the other, not both. The OP should get the right interface to their database that supports promises and then use ONLY promises to program with it. Then, they can just return the promise directly and the caller can use `await`. – jfriend00 Nov 15 '19 at 17:03
0

Unlike the other lines, line 4 executes a database query which works asynchronously and follows the callback pattern. One way to defer the response until the database query is done is to make execute function follow the callback pattern too:

execute(sql, callback) {
  this.db.query(sql, function (err, results) {
    if (err) {
      logger.log("error", err);
      return callback(err)
    }

    if (results.length)
      return callback(null, results);
    return callback();
  });
}

In this way you can pass the database query result as an argument to the callback and return the response to HTTP request inside that callback:

router.post(routes.availability, function (req, res) {
    const sqlClient = require('../framework/db/mysql');
    var query = "Select 1 as 'data' from dual;";
    sqlClient.execute(query, (err, result) => {
      if (err) {
        return res.status(500).send("Error")
      }
      res.status(200).send(toString(result))
    });
})
antonku
  • 7,377
  • 2
  • 15
  • 21