Milos
Milos

Reputation: 1253

How to properly chain promises inside of a forEach loop in Javascript

I'm using mongo and need to do an async call for each item inside of a loop. I'd like to execute another command once all of the promises inside of the loop have completed, but so far the promises in the loop seem to be completing after the code that's in the then that's after the loop.

Essentially i'd like the order to be

Loop promises then other code

instead of what it is now which is

other code Loop promises

MongoClient.connect(connecturl)
.then((client) => {
  databases.forEach((val) => {
    val.collection.forEach((valcol) => {
      client.db(val.databasename).stats() //(This is the async call)
      .then((stats) => {
        //Do stuff here with the stats of each collection
      })
    })
  })
})
.then(() => {
  //Do this stuff after everything is finished above this line
})
.catch((error) => {
}

Any assistance would be appreciated on this one.

Upvotes: 2

Views: 2172

Answers (1)

jfriend00
jfriend00

Reputation: 707178

Assuming the things you are using .forEach() on are iterables (arrays or something like that), you can use async/await to serialize a for/of loop:

    MongoClient.connect(connecturl).then(async (client) => {
        for (let db of databases) {
            for (let valcol of db.collection) {
                let stats = await client.db(db.databasename).stats();
                // Do stuff here with the stats of each collection
            }
        }
    }).then(() => {
        // Do this stuff after everything is finished above this line
    }).catch((error) => {
        // process error
    })

If you wanted to stick with your .forEach() loops, you could make it all work if you did things in parallel and used Promise.all() to know when it's all done:

MongoClient.connect(connecturl).then((client) => {
    let promises = [];
    databases.forEach((val) => {
        val.collection.forEach((valcol) => {
            let p = client.db(val.databasename).stats().then((stats) => {
                // Do stuff here with the stats of each collection
            });
            promises.push(p);
        }); 
    });
    return Promise.all(promises);
}).then(() => {
    // Do this stuff after everything is finished above this line
}).catch((error) => {
    // process error here
});

Upvotes: 4

Related Questions