node.jsmongooseasync-awaitpromiseasynchronous-javascript

Node.js Promise.all method not working as expected for saving multiple mongoose documents


I know of the Model.create(documentsArray) and also Model.bulkSave(documentsArray) mongoose API's.

I was just experimenting with the Promise.all the following way -


const promises = []
for(let i=1; i++; i<1000) {
 const promise = new UserModel({userId: Math.random() * 1000}).save()
 promises.push(promise)
}

console.time('t1')
await Promise.all(promises)
console.timeEnd('t1') // takes about 329.189ms

If I replace the insertion logic by -

console.time('t2')
for(const promise of promises) {
  await promise
}
console.timeEnd('t2') // takes about 335.268ms

As commented above both t1 and t2 are nearly same! Why Promise.all don't sends all save requests to the database at once if I understand it correctly. What am I missing here?

NOTE: above both blocks are meant to


Solution

  • Imagine ordering 3 packages from Amazon. Your orders are analogous to "promises" that you can wait for.

    What you are contemplating with Promise.all(promises) vs for (p of promises) await p; can be adapted to this analogy.

    Promise.all is like saying "Wait until all my packages have arrived." It doesn't matter what order they arrive in, but your waiting concludes when the final package arrives -- in this case, when you have all 3 packages.

    for-await is like waiting for them individually: "Wait until my headphones arrive, then wait until my pillow arrives, then wait until my can-opener arrives." In this case, if the can-opener arrives first, then you spend most of your time waiting for the headphones, and when it comes time to wait for the can-opener, it may have already arrived or there may be a bit more time to wait for it. In fact, it may have arrived before the headphones, you just weren't explicitly waiting for that particular package at that moment. It may very well be sitting on your porch already. If the can-opener is on back-order but the headphones arrived next day then you will spend most of your time waiting for the can-opener, and the headphones and pillow may have already arrived long ago. You aren't done waiting for everything until that last package arrives though.

    So the overall duration is how long it takes the longest delivery to arrive.

    It's critically important to note that the order in which you wait for your deliveries has nothing to do with how long it takes for the deliveries to arrive. You can't make your Amazon orders arrive more quickly or more slowly by adjusting the order of which package you hope will arrive next. You can sit by your front door wishfully waiting for only the headphones, effectively ignoring if and when the delivery person drops off your pillow or can-opener. What you were hoping for doesn't affect what package arrives first or how long it takes.

    Promise.all could correctly be implemented internally with your for-await loop. So it shouldn't be surprising that they take the same amount of time.


    Or consider conceiving a baby and ordering a pizza on the same day. This will take about nine months until you can say both have been delivered. If you wait for only the baby first, your pizza will be...quite cold, that's all.