3

I know node.js run asynchronously, so outer functions execute earlier than the inner. But what is the way to access the notification array outside the for loop? I would like to access all the values in array at once, is this feasible?

var notification=[];

for(var j=0;j<6; j++)
{
     getNotification(response[j].sender_id,function(results)     // a function called
     {
         notification[j] =results;
         console.log(notification); // output: correct   
     });          
}
console.log(notification);       // output: [], need notification array values here
3
  • What's the error you're experiencing? Commented Aug 2, 2013 at 13:23
  • You can't. At least not reliably, what you have is a race condition, that is guaranteed to be lost. You use them in the callback. You can however, keep the notification in a closure and use it in other functions once the callback is complete, to make it look like you're doing this. This is precisely what the callback is for. To run a series of operations, within the scope of some asynchronous operation. Commented Aug 2, 2013 at 13:26
  • Also, creating functions in a loop is a bad idea. You should define your callback outside of your for loop, and use it as an argument. Commented Aug 2, 2013 at 13:41

3 Answers 3

1

EDIT: If you don't want to use third party libs, this is how to do this in your own code.

/* jshint node:true*/


function getNotifications(responses, callbackToMainProgramLogic) {
    'use strict';
    var results = [];

    function getNotificationAsync(response) {
        getNotification(response.sender_id, function (data) {
            results.push(data);

            if (responses.length) {
                getNotificationAsync(responses.pop());//If there are still responses, launch another async getNotification.
            } else {
                callbackToMainProgramLogic(results);//IF there aren't we're done, and we return to main program flow
            }
        });
    }

    getNotificationAsync(responses.pop());
}

getNotifications(someArrayOfResonses, function (dataFromNotifications) {
    console.log('The collected data: ' + JSON.stringify(dataFromNotifications, 0, 4));
});

If you absolutely must, you could do something ridiculous like this. Your logic in the loopUntilDatReceived would be waiting for array sizes, not waiting for a non-empty string, but the idea is similar, and you shouldn't be using this anyway! :)

var fileData = '';
fs.readFile('blah.js', function (err, data) { //Async operation, similar to your issue.
    'use strict';
    fileData = data;
    console.log('The Data: ' + data);
});

function loopUntilDataReceived() {
    'use strict';
    process.nextTick(function () {//A straight while loop would block the event loop, so we do this once per loop around the event loop.  
        if (fileData === '') {
            console.log('No Data Yet');
            loopUntilDataReceived();
        } else {
            console.log('Finally: ' + fileData);
        }
    });
}

loopUntilDataReceived();

Did I mention this is ridiculous? Honestly, this is an awful idea, but it may help you understand what is going on and how the Node event loop works, and why what you want is not possible. AND why the other posts about callbacks, and flow control libraries are the way to go.

Sign up to request clarification or add additional context in comments.

Comments

0

First off, you're having a closure issue in your code (please see the details here)

Then, you simply can't have the array values just next to the loop, because the values are not ready at this point. You need to wait until all 6 of your getNotification calls get resolved. You can do that with the async library. Something like:

var notification = [];

function createRequest (index) {
    return function (callback) {
        getNotification(response[index].sender_id, function(results) {
            notification[index] = results;
            callback(results);
        });
    }
}

var requests = [];
for(var j=0;j<6; j++) {
    requests.push(createRequest(j));
}

async.parallel(requests, function (allResults) {
    // notifications array is ready at this point
    // the data should also be available in the allResults array
    console.log(notifications);
});

Comments

0

Send a callback to the notification loop like this:

var notification=[];

getNotificationArray( function() {
  console.log(notification);
});

function getNotificationArray (callback)
{
  for(var j=0;j<6; j++)
  {
    getNotification(response[j].sender_id,function(results)     // a function called
    {
      notification[j] =results;
      console.log(notification); // output: correct   
    });          
  }
  callback();
}

4 Comments

Actually, sorry this won't work. I realized that your callback is in the wrong place. getNotification() is the async portion. So your callback() is poorly located, pluse there is iteration going on, so you need some logic for waiting for multiple iterations of getNotification.
Yes, now it dawns on me, too.
I updated my answer to include a non-third party lib function, similar to what you attempted. Check it out.
Yes, that's the right order. Nice solution, I wish I could up-vote. Starred for later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.