How can I wait for a series of asynchronous processes to end so that I can do something after they end?


#1

How can I wait for a series of asynchronous processes to end so that I can do something after they end?

Here is a sample of what I am trying to do that illustrates the problem:

const urls_to_do = {
    
    link1: { url: 'url' },
    link2: { url: 'url' }

};

// place to hold urls that are finished
let urls_done = {};


for (const prop in urls_to_do){
    
    // the request function is performed asynchrounously
    request(urls_to_do[property].prop, function (error, response, body) {
        
        console.log('finished ' +  urls_to_do[property].prop);

        // add the result to urls_done
        urls_done[url_to_do[property].prop ] = urls_to_do[property].prop;

    });
    
}

// now I want to do something with all of the urls that are done, but doing 
// anything here will not work.
//  this is empty because it runs BEFORE any requests in the loop are done
console.log(urls_done);

I want to wait until the for-in loop is done so that I can proceed. Is there a way to do this? I am pretty new to async javascript so any pointers would be helpful. The code in the for-in loop must run asynchronously.

I am doing this on Node, and running the latest version.


#2

Assuming that your request method returns a Promise, you can use Promise.all.

From the docs:

The Promise.all(iterable) method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.

Something like this should work for you:

const urls = [
  'http://url1',
  'http://url2'
]

Promise.all(urls.map(url =>
  request(url).then((data) => {
    console.log(`Finished ${url}`);
    // Do something with your data here
  });
});

HTH


#3

Promise.all()


#4

Thanks, that seems like what I am looking for.

What if I know that some promises will be definitely be rejected and just want to collect the status on each? For example, if a promise is rejected, add something to an array (or object) with with the status of "rejected," and if the promise succeeded, add it with the status of success? If the promise.all ends on the first rejection, I will not collect the status of the rest of the promises.

Sorry for the basic async questions here - my javascript knowledge is ancient!


#5

In that case you don't use Promise.all() on the original promises, but on promises where you catch the rejection beforehand.

// untested
var p[p.length] = request.then(() => 'resolved').catch(() => 'rejected')
// etc.
Promise.all(p).then((data) => { ... })

#6

Thanks, but I am having a hard time understanding your example. Could you make it a bit more verbose or fill it out a bit more for me?


closed #7

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.