1

I wonder what is the proper way to do this?

while(newList.length < 10){
            async.series([
                function(callback){         
                    async.eachSeries(rest,function(id,next){
                        if(getDistance(myLoc,id) < 5){
                            newList.push(id);
                        }
                        next();
                    });
                    callback();
                },
                function(callback){
                    var size = 10 - newList.length
                    rest = getPlaces()
                    callback();
                }], function(err,results){
                    if(err) console.log('error occured in : ' + err);
                });
        }

rest is populated by 10 new places every run, while the first step of the asyc process is to find out if the distance of the 10 places is within 5km, if its within 5 km, then it's added to newList, if not then we'll do another loop until it finds 10 places with its distance within 5km

while really the idea is to re-iterate until my newList is filled with 10 (places with distance < 10 km), when I try to run this, it went over everything just once and won't loop for the second run.

2
  • 1
    your code is pretty complicated, and most of the users won't even try to understand it, can you simplify it by removing needless parts? Commented Sep 28, 2016 at 12:44
  • Done, I hope it's simple enough @Hatsuney Commented Sep 28, 2016 at 12:50

3 Answers 3

1

Okay, so you have several problems here.
Let's start with this:

function(callback){         
    async.eachSeries(rest,function(id,next){
        if(getDistance(myLoc,id) < 5){
            newList.push(id);
        }
        next();
    });
    callback();
}

You're not waiting for the output of eachSeries, you're starting it, and immediately calling back.
That function will fill out your newList independently, maybe immediately, maybe after a slight delay; you can't know that, because you called back right away.
You also don't gain anything by using series here, because it's supposed to run functions each one after the previous function has completed.
Your code might end up working like this:

  • start async.series
  • run the first function
  • the function begins an async.eachSeries
  • the function calls back
  • second function starts, and newList is still not filled
  • second function ends
  • end of the loop
  • newList is still not filled

Other than that, your while function doesn't have to wait for anything either, it will just mindlessly run async.series over and over again, until your newList gets filled, most likely taking up tons of resources. You can use functions like async.whilst instead, for example:

async.whilst(
    function() { return newList.length < 10; },
    function(callback) {
        ...
    }, function(err, results) {
        console.log('loop has ended')
    }
)

Also, you should probably use the callbacks from series to generate a results array, and process them at the end of a loop, instead of letting the functions fill stuff out randomly and unpredictably.
For example:

function(callback){
    var list = []
    async.eachSeries(rest,function(id,next){
        if(getDistance(myLoc,id) < 5){
            list.push(id);
        }
        next();
    }, function(err) {
        callback(err, list);
    });
}

I hope this shed some light on your problems.

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

3 Comments

I tried this way, but ended up the list filling up to 4xx, while it should end the loop when the list is 10. I wonder what happened?
take it slow, step by step, making sure everything works as intended on the way
Nvm got it! I forgot to call the callback. Thanks!
1

Use async whilst instead of a regular while:

var newList = [];
async.whilst(
    function(){ return newList.length < 10;},
    function(done) {
        async.series([
           function(callback){  
               var size = 10 - newList.length
               rest = getPlaces()
               callback();       
           },
           function(callback){
               async.eachSeries(rest,function(id,next){
                   if(getDistance(myLoc,id) < 5){
                        newList.push(id);
                   }
                   next();
               });
               callback();
           }], 
           function(err,results){
               if(err) console.log('error occured in : ' + err);
               done(err, newList);
           };    
    },
    function(results) {
        // New list has been filled
    }
})

Comments

0

My suggestion would be to have a boolean variable outside the while scope, which is by default true, and which is set to false when the async function fills the list with 10 elements. Hope that helps.

1 Comment

Also, before actually using the list variable in other context, you should check whether, the filling condition is full, as JS will continue running async code in the background and may start a function on the yet-unpopulated variable from memory instead the instance of the variable, that is being populated by the async code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.