1

I have a Node.js function to fetch some value from DB table

var GetPoints = function(ibmdb, dbConnection, msisdn) {
    ibmdb.open(dbConnection, function(err, conn) {
        if (err) {
            //Error
        } else {
            conn.query('SELECT id,msisdn,points FROM t_points WHERE msisdn =' + msisdn, function(err, data) {
                console.log(err);
                if (!err) {
                    conn.close(function(err) {
                        if (!err) {}
                    });
                    consele.log(data);
                    //return data[0].POINTS;
                } else {
                    //Error
                }
            });
        }
        console.log("points" + points);
    });
}

I want to know how I can access the data object when I call this function from outside

 var data = GetPoints(ibmdb, dbConnection, msisdn);

The value is coming correctly when I do a console.log

laggingreflex
  • 32,948
  • 35
  • 141
  • 196
Codemator
  • 513
  • 1
  • 10
  • 19
  • No Return data is not working..I trued to use return data after line console.log(data). But it seems the value is only valid for the context of the internal function – Codemator Jun 27 '15 at 10:18
  • You mean from an async function, i.e. `conn.query`'s callback function? You can't unfortunately. Your `data` is only available inside that callback. – laggingreflex Jun 27 '15 at 10:19
  • There is no way I can get the data[0].POINTS outside the context? – Codemator Jun 27 '15 at 10:22
  • assign a variable with outside scope with the return value. take a small interval for checking the variable and if set do something. – Nina Scholz Jun 27 '15 at 10:23
  • Problem is that data is available AFTER query is executed. But GetPoints returns when query is started. So you can store data somewhere and wait query completion or use it inside callback. – Dmitry Poroh Jun 27 '15 at 10:26

2 Answers2

6

You can't return the value from an async function directly. Promises are generally used this situation. You return a promise which can later be called .then upon to retrieve the said value.

var Promise = require('bluebird');
var GetPoints = function(ibmdb, dbConnection, msisdn) {
    // return a Promise
    return new Promise(function(resolve){
        ibmdb.open(dbConnection, function(err, conn) {
            if(err) throw err; // throw the error for it to be caught
            …
            conn.query('SELECT …', function(err, data) {
                if(err) throw err;
                …
                consele.log(data);
                //return data[0].POINTS;
                resolve(data);
}); }); }); }

GetPoints().then(function(data){
    // do something with data
}).catch(function(err){
    // handle err
});

Additionally, Bluebird has a promisify function that turns an async function (that takes a callback) into a function that returns a Promise. It makes the above code much simpler:

Note: Although I was reluctant because if you're using MySQL with which the promisification could be a little tricky: 1, 2. But For now I've added .promisifyAll where it might seem redundant as it will likely be executed more than once, but hopefully bluebird's promisification is smart enough to handle this. Nonetheless if you manage to promisify more efficiently you can just remove the redundant promisifyAll and just use X.yyyAsync methods as described:

function GetConnection(ibmdb, dbConnection, msisdn){
    Promise.promisifyAll(ibmdb);
    return ibmdb.openAsync();
}

function getData(conn){
    Promise.promisifyAll(conn);
    return conn.queryAsync('SELECT …');
}

GetConnection()
.then(getData)
.then(function(data){
    // do something with data        
})
Community
  • 1
  • 1
laggingreflex
  • 32,948
  • 35
  • 141
  • 196
  • Bluebird's `promisify` functions could likely be used here to avoid creating new Promises directly (which often aren't needed and are prone to mistakes). – Matt Hamann Jun 27 '15 at 18:40
  • @MattHamann Excellent point. I love promisification myself, but I was reluctant in this case because I found that with MySQL it can be a little tricky: [1](http://stackoverflow.com/questions/24797314/how-will-a-promisified-mysql-module-work-with-nodejs), [2](http://stackoverflow.com/questions/28485032/how-to-promisify-a-mysql-function-using-bluebird). Nonetheless, I've expanded on both the promisification part and the related issue with mysql. I also corrected the mistake of not throwing the errors (hopefully that was the only mistake). – laggingreflex Jun 27 '15 at 22:41
  • all i could return is a promisify object. – PrivateOmega Nov 02 '17 at 04:42
0

The callback function you gave after the SQL query gets executed asynchronously. Instead of trying to get that data outside the function, you should try to perform whatever you need to do inside. Keep in mind you can create another function and call it with the data to continue your work.

Ram Vennam
  • 3,536
  • 1
  • 12
  • 19