0

I am new to Node and clearly struggling with the callback concept. How can I return the array only after the query is completed? I've seen similar node with mssql module examples but I've failed solve my problem

function myFunction () {
    var arr = [];
    var connection = new sql.Connection(dbConfig, function (err) {
        var request = new sql.Request(connection);

        request.query('select top 10 Name from User', function (err, recordset) {
            if (err) {
                console.log('error');
            }

            for (var id in recordset) {
                arr.push(recordset[id]["Name"]);
            }
          
        });

    });
};

myFunction ();

Eventually, I want to 'return' the resultset in array or JSON format so I can use it easier.

Ben77
  • 65
  • 2
  • 9
  • 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) – Joe Clay May 22 '17 at 13:39
  • Thanks! That's one of the pages I went through while studying. There are a few more but I am struggling to implement the logic and achieve my goal in my shared code. – Ben77 May 22 '17 at 15:16

1 Answers1

0

In Node, the two main (but not only!) ways that you can 'return' from an asynchronous function are:

Callbacks

Similar to how request.query takes a callback as a parameter, you can also do so:

function myFunction(cb) {
    var arr = [];
    var connection = new sql.Connection(dbConfig, function (err) {
        var request = new sql.Request(connection);

        request.query('select top 10 Name from User', function (err, recordset) {
            if (err) {
                console.log('error');
                cb(err, null);
                return;
            }

            for (var id in recordset) {
                arr.push(recordset[id]["Name"]);
            }

            cb(null, arr);
        });

    });
};

Notice how I've followed the same conventions as other Node callbacks - errors as the first parameter, the returned data as the second parameter. With this in place, you can use your function like so:

myFunction(function (err, data) {
    if (err) {
        /* error handling */
    }

    /* do stuff with data here */
});

Promises

A somewhat more modern abstraction around asynchrony is Promises - these represent the asynchronous thing that is going to happen as an object, which will either be resolved or rejected. Here's how you could apply this pattern to your function:

function myFunction() {
    return new Promise(function (resolve, reject) {
       var arr = [];
       var connection = new sql.Connection(dbConfig, function (err) {
           var request = new sql.Request(connection);

           request.query('select top 10 Name from User', function (err, recordset) {
               if (err) {
                    console.log('error');
                    reject(err);
                    return;
               }

               for (var id in recordset) {
                   arr.push(recordset[id]["Name"]);
               }

               resolve(arr);
           });
        });
    });
};

You can then chain .then and .catch onto the returned Promise to handle the result:

myFunction()
    .then(function (data) {
        /* ... */
    })
    .catch(function (err) {
        /* ... */
    });

Both of these examples are very basic - there's a lot more you can do, especially when it comes to Promises (which are very well suited to chaining lots of asynchronous stuff together). I'd encourage you to research both of these options further.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • Thank you Joe. However, I am still struggling to read the populated array from outside the DB function. Could you kindly add that so I can see the full picture? I am trying to follow the MVC structure, that's why I need to bring out the resultset out of the function and the module itself. – Ben77 May 23 '17 at 01:36
  • @Ben77: The populated array is the `data` parameter in your callback/`then` handler. You have to access it through that handler - it's the only way you can guarantee the async operation has finished first. – Joe Clay May 23 '17 at 08:54
  • 1
    Thanks! I will be on my way to read/research more on callbacks and promises. – Ben77 May 26 '17 at 03:11