-3

I am trying to write a module which returns a value from MySQL database based on the key that gets passed to the function.

The below code when tested in standalone works fine, i was able to get the result back, but when i try to get the results from a function call i get undefined.

var value = getKey("tc_api_user_key");

I suspect it due to the return statements. How should i make the calling function wait for the results.

var mysql = require('promise-mysql')
    , dbConnect = require('../connection.js')
    , fs = require('fs')
    , select = fs.readFileSync(__dirname + '/queries/getallkey.sql').toString();

let getKey = (key_id) => {
mysql.createConnection(dbConnect.getConnection()).then(function(conn){
    var result = conn.query(select);
    conn.end();
    return result;
}).then(function(rows){
    // Logs out a list of hobbits
         Object.keys(rows).forEach(function(key) {
                    var item = rows[key];
                      if (key_id == item.key_id) {
                           return item.key_value;
                      }
                    });
});

}    

 var value = getKey("tc_api_user_key");
 console.log(value) 

This issue is not with the conn.query(), the function works as expected if console.out the result is used, its just not usable in function call. May be due to the async nature of the call.

Sudheej
  • 1,873
  • 6
  • 30
  • 57
  • 2
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Matt Morgan Apr 08 '18 at 16:57
  • 2
    Your `conn.query()` call is asynchronous. You need to pass it a callback and handle the response in there. – Matt Morgan Apr 08 '18 at 16:58

2 Answers2

6

There are two ways to do it. The async way or the promise way.

Async way

let getKey = async (key_id) => {
  let conn = await mysql.createConnection(dbConnect.getConnection())
  let rows = conn.query(select);
  conn.end();
  for ([key, item] of Object.entries(rows))
  {
    if (key_id == item.key_id)
      return item.key_value;
  }
}

async function do() {
  var value = await getKey("tc_api_user_key");
  console.log(value)
}

do()

Promise way

In this you return a Promise and inside the promise when you want to return the value you resolve the promise.

let getKey = (key_id) => {
    return new Promise( (resolve) =>
    mysql.createConnection(dbConnect.getConnection()).then(function (conn) {
        var result = conn.query(select);
        conn.end();
        return result;
    }).then(function (rows) {
        for ([key, item] of Object.entries(rows))
        {
            if (key_id == item.key_id) {
                resolve(item.key_value);
                break;
            }
        }
    })
    );
};

getKey("tc_api_user_key").then(value => {
    console.log(value)
});

Of course for error handling and all you should reject the promise if the value is not found. But the above code should give you a key idea of how to do it

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
-8

Let me answer my own question, thanks to a wonderful feature "callbacks" which i learnt it the hard way.

Here it goes, when you abstract these modules its good to have a callback function which does the job for handling the calls from your invoking js and you can handle these results back efficiently.

Abstracted module which handles the database call

var mysql = require('promise-mysql')
    , dbConnect = require('../connection.js')
    , fs = require('fs')
    , select = fs.readFileSync(__dirname + '/queries/getallkey.sql').toString();


async function getKey (key_id,callback) {

try {
  callback(undefined,await dbTask(key_id)); 
}
catch(err) {
  callback(err);
}
}    

let dbTask = (key_id) => {

  return new Promise (function (resolve,reject) {
  mysql.createConnection(dbConnect.getConnection()).then(function(conn){
    var result = conn.query(select);
    conn.end();
    return result;
}).then(function(rows){
    // Logs out a list of hobbits
         Object.keys(rows).forEach(function(key) {
                    var item = rows[key];
                      if (key_id == item.key_id) {

                        resolve (item.key_value);

                      }
                    });
         });
     });

  }

Invoking Module

let getTeamcityServer = (serverUrl, callback) => {

  try {

    selectKey.getKey("tc_api_user_key",(errorMessage, api_pass) => {

      if (errorMessage) {
        callback(errorMessage);
      }
      else {

          auth = vault.decrypt(api_pass);
          callback(undefined,teamcity.create({
          url: serverUrl,
          username: "XXXXXXXX",
          password: auth

          }));

      }

    });

  }
  catch(err) {

    callback(err);


  }



}
Sudheej
  • 1,873
  • 6
  • 30
  • 57
  • 2
    So you mix Async, await, Promise, callbacks all of them in one good soup – Tarun Lalwani Apr 11 '18 at 06:40
  • Yeah that’s because nobody could suggest a better way – Sudheej Apr 11 '18 at 11:41
  • 3
    This is an awful answer and worst it mixes patterns and includes things like `async` with no `await` then proceeds to use a callback. Just looks like your trying to avoid giving the bounty away to the obviously better answer showcasing the best practice for es6 below. Please remove your low quality answer. – li x Apr 12 '18 at 15:21
  • why dont you provide an agreeable/attractive answer with justification on why something cannot be this, node js is low-level is there any ruleset preventing you to write this code ? – Sudheej Apr 12 '18 at 22:08
  • @lix the OP can't award the bounty to their own answer. So the bounty has to be awarded to any other answer, or, if not awarded, the system choose the winning answer, which isn't this one at the moment. – rene Apr 12 '18 at 22:25
  • I see, sadly it didn't stop him down voting me 5 times. – li x Apr 12 '18 at 22:26
  • 1
    @lix I expect that to be reversed at 03:00 UTC by the serial voting script. If that isn't the case flag one of your posts for moderator attention and explain what happened. – rene Apr 12 '18 at 22:29
  • 1
    I awarded the bounty to the correct answer guys. Thank you. – Sudheej Apr 13 '18 at 00:11