1

I have an array of elements through which I'am iterating and making some RPC calls to get the response, push the response into array and send it back to UI to display. But these responses are asynchronous and not getting pushed into array. So when the response is received at UI side, it is empty.

NodeJS code:

app.get('/getData/:obj', function(req,res, next){

    data = JSON.parse(req.params.obj);

    var options = ["location","start","end","user"];

    /*Data looks like this*/

    /*[ { start: '12-05-2016' },
      { end: '12-09-2016' },
      { location: [ 'US','UK' ] },
      { user: [ 'Jim','Jack' ] } ]*/

    var requestArray = [];
    for(var d in data) {
        if(options.indexOf(d) > -1 ) {
            var rpcRequest = {};
            rpcRequest[d] = data[d]
            requestArray.push(rpcRequest);
        }

    }
    console.log(requestArray);
    var resp = []

    for(var i in requestArray)    {
        var item = requestArray[i];
        _.each(item, function(value, key) {
            console.log('key :'+key+'\tvalue: '+value);
            if(util.isArray(value)) {
                for(var val in value)   {
                    var request = {};
                    request[key] = value[val];
                    console.log('\tkey :'+key+'\tvalue: '+value[val]);
                    console.log('request: '+JSON.stringify(request));

                    switch(key) {
                        case "location": 
                            rpcClient.location(request, function(err, response) {

                                response = (JSON.stringify(response)); //asynchronous  response

                                resp.push(response); //push response into array

                            });
                            break;
                        case "user":
                            rpcClient.user(request, function(err, response) {

                                response = JSON.stringify(response); //asynchronous  response

                                resp.push(response); //push response into array

                            });
                            break;

                        default: break;
                    }


                }
            }

        });

    }

    console.log(resp);
    res.send({d:resp}); // send the response array, but it is empty
}); 

How do I make the pushing of data into array synchronous or get the proper data in some way. I have heard of async module, nut not quite sure how to use it here.

Seeking help! Thank you :)

Yajnesh Rai
  • 290
  • 1
  • 6
  • 17
  • Related, but not quite a duplicate: http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – T.J. Crowder Dec 12 '16 at 07:31

1 Answers1

1

You wait to call res.send until the last response has been received.

So you keep track of how many responses you've received, and when you receive the last one, then you call res.send from within the response callback for that final response.

Here's a simplified example:

var requests = [
  "one", "two", "three", "four", "five"
];
var responses = [];
requests.forEach(function(request) {
  // setTimeout to get something async
  setTimeout(function() {
    // Now we're in the async operation callback
    var response = "Response for " + request;
    console.log("Got: " + response);
    
    // Save the response
    responses.push(response);
    
    // Is it the last one?
    if (responses.length == requests.length) {
      // We're done, this is where you'd do
      // `res.send`
      console.log("Done! Got all responses: ", responses);
    }
  }, Math.random() * 1000);
});

Side note: Don't use for-in to loop through arrays unless you're doing it on purpose because of a sparse array; that's not what it's for. See this question's answers for your various options for looping through arrays.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for the answer! But I'm not sure about time that the response may take, so using a fixed timeout wouldn't help in my case. – Yajnesh Rai Dec 12 '16 at 07:39
  • @YajneshRai: I haven't suggested using a fixed timeout. The `setTimeout` in the above, as the comment says, is to emulate your async operations for the purposes of the example. You wouldn't really use `setTimeout`, you'd just do the same thing with your real async operations. The key is that you call `res.send` from within an async completion handler, when you've received all of the responses. – T.J. Crowder Dec 12 '16 at 07:47