What causes the resolution of an array of promises to be slower when each promise is individually resolved in a while loop, as opposed to resolving them all at

I have a model called Posts in my mongoDB database, which contains an array of references to a model called Comments.

One of the get requests in my Express application requires me to respond with an array of all Posts in the database, where each Post includes an array of all its associated comments.

To achieve this, I first fetched all the Posts using the find method, resulting in an array of posts, each containing references to their respective comments as per the model structure.

To resolve these references, I utilized the populate method provided by mongoose, which replaced the references with actual comment objects from the database for a single post instance.

await post.populate("comments").execPopulate();

Here, "post" represents a single post instance after resolving all its comment references into comment objects.

However, to perform this resolution for every post individually, I experimented with two methods. In both cases, allPosts refers to the array of retrieved posts from the initial find query.

  1. Initially, I used the execPopulate operation to create an array of promises for each post without waiting for their resolution. Subsequently, I used Promise.all() to proceed with further operations once all promises were resolved.
let promiseArray = allPosts.map((post) => {
    return post.populate("comments").execPopulate();
});


Promise.all(promiseArray).then((posts) => {
    
    let responseArray = posts.map((post) => {
        return {
            comments: filterComments(post.comments),
            _id: post._id,
            title: post.title,
            commentcount: countComments(post.comments),
        };
    });

    return res.send(responseArray);
});

  1. Alternatively, I implemented a while loop where I waited for each post to be resolved individually in every iteration before formatting and pushing the post object into a response array. Once all posts were processed, I sent the response array back.
let responseArray = [];
let length = allPosts.length;
let counter = allPosts.length;

while (counter) {
    let post = allPosts[length - counter]

    await post.populate('comments').execPopulate();

    responseArray.push({
        comments: filterComments(post.comments),
        _id: post._id,
        title: post.title,
        commentcount: countComments(post.comments),
    })

    counter--;
}

return res.send(responseArray);

When comparing the performance between these two approaches with around 150 posts, the process using the while loop took almost three times longer than the one utilizing Promise.all(). I am uncertain about the nuances of the JavaScript event loop; hence, I am seeking insights on what might be causing this difference in execution time.

TL;DR :

I have several async operations to execute on each item in an array; I tested:

  1. Iterating through the array and storing unresolved promises in an array, then proceeding with further actions after using Promise.all() on the promises array

  2. Going through the array with a while loop, executing the async task for each element on every cycle

The while loop approach significantly increases processing time compared to resolving promises with Promise.all().

Answer №1

Although I am not a seasoned expert in JavaScript development, my understanding is as follows:

Event loops do not operate on a single thread, so when using Promise.all(), promises are executed concurrently. Using Promise.all() typically runs requests asynchronously in parallel, saving time and making it faster than awaiting each promise individually.

Note: Promises will execute once they are created. In your code, promises have been created within the map method.

Promise.all simply waits for each promise to be fulfilled.

In contrast, async/await creates a promise, waits for it to resolve, then moves on to the next.

Alternatively, you can directly populate comments for all posts using the code below, which offers a faster solution than both methods:

const PostsWithComments = await PostsModel.find({}).populate("comments").exec()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: ytcfg and __ytRIL are undefined and cannot be referenced

For several months, I had smooth sailing with the YouTube IFrame Player API until recently when an unexpected exception popped up upon loading the player: Uncaught ReferenceError: ytcfg is not defined Upon inspecting the iframe, I noticed that yt.setConfig ...

Develop a built-in Button for Liking posts

Currently, I am encountering an issue with the JavaScript SDK where I am unable to create a built-in Like button. After researching, I came across this helpful resource: https://developers.facebook.com/docs/opengraph/actions/builtin/likes/ The solution pr ...

What is the best way to title an uploaded chunk with HTML5?

Here is the script I am working with: function upload_by_chunks() { var chunk_size = 1048576; // 1MB function slice(start, end) { if (file.slice) { return file.slice(start, end); } else if (file.webkitSlice) { ...

Removing buttons from a table row dynamically

Below is how I am adding the Button to Element: (this.sample as any).element.addEventListener("mouseover", function (e) { if ((e.target as HTMLElement).classList.contains("e-rowcell")) { let ele: Element = e.target as Element; let ro ...

Attempting to modify the environmental variable within node.js via the terminal proves to be a fruitless endeavor as the value consistently remains undefined

Recently, I entered the world of backend development and came across this JS code utilizing express: const express = require('express'); const app = express(); const port = process.env.PORT || '3000'; app.listen(port, ()=> console.lo ...

Utilizing a forEach loop in PDF-kit to display images in a side-by-side layout

I have an API that is capable of adding pictures to a PDF after sending a request to the database. I have successfully made it work for one picture, but I am wondering how to display images side by side. Currently, the images are stacked on top of each oth ...

What is the best way to display only li elements that possess a specific class utilizing javascript / jquery?

I have a bunch of li's: <ul> <li class="one"></li> <li class="one"></li> <li class="two"></li> </ul> and I want to display only the ones with the class "one" I attempted something like thi ...

Encountering issues with Monaco Editor's autocomplete functionality in React

I'm facing an issue with implementing autocomplete in the Monaco Editor using a file called tf.d.ts that contains all the definitions in TypeScript. Despite several attempts, the autocomplete feature is not working as expected. import React, { useRef, ...

Problems with JQuery Ajax Json Response

Provided Form Section: <script type="text/javascript" src="js/aboneol.js"></script> <h4>Subscribe</h4> <div class="newsletter"> <span id="aboneolerror">< ...

What are the steps for running mongodb aggregations on documents with multiple levels of nesting?

In my mongodb database, there is a collection named tasks. The collection consists of tasks with unique identifiers such as T1.1, which are subtasks of parent tasks like T1, and the hierarchy can have multiple levels. Currently, the database is running on ...

Converting a string array to an array object in JavaScript: A step-by-step guide

My task involves extracting an array from a string and manipulating its objects. var arrayString = "[{'name': 'Ruwaida Abdo'}, {'name': 'Najlaa Saadi'}]"; This scenario arises when working with a JSON file where ce ...

What is the process for retrieving data from a website?

Currently, I am in the process of setting up an automated test using the basic page object pattern. The objective is to open Google, input a search query, click on a link from the results, and retrieve the information. So far, I have successfully navigated ...

Can JavaScript be Utilized to Create Dynamic Layouts Successfully?

Are you curious about the viability of using Javascript to create fluid website layouts? While it is possible, how does it compare in terms of performance and complexity when compared to other methods like CSS3/HTML5? Take a look at the function below that ...

How to toggle a boolean variable in AngularJS when transitioning between states

Just getting started with AngularJS and trying to figure out how to tackle this issue. I have set up the following route: name: "Tracker", url: "/tracker/:period", and I have 3 distinct states for which I've created 3 separate functions to facilit ...

Expanding content based on height using React

I have successfully implemented the show more/show less feature. However, my issue is that I would like it to be based on the number of lines or screen height rather than the number of characters. This is because the current setup may look awkward on certa ...

Is it possible to synchronize Vue data values with global store state values?

I need help updating my data values with values from store.js. Whenever I try the code below, I keep getting a blank page error. Here's how I have it set up in App.vue: data() { return { storeState: store.state, Counter: this.storeState.C ...

How can I showcase array elements using checkboxes in an Ionic framework?

Having a simple issue where I am fetching data from firebase into an array list and need to display it with checkboxes. Can you assist me in this? The 'tasks' array fetched from firebase is available, just looking to show it within checkboxes. Th ...

Exploring the world of Node.js and the power of 64-bit var

Currently, I am developing a Node.js application that communicates via TCP with a C++ server. The server utilizes a binary protocol similar to Protocol Buffers but not identical. One of the data types returned by the server is an unsigned 64-bit integer ( ...

The $scope object in AngularJS has not been properly defined and

I am facing an issue with retrieving the value of email in my controller. It always returns 'undefined'. Here is my form: <form role="form" novalidate> <div class="form-group"> <input type="email" ng-model="user.emai ...

What is the best way to incorporate a counter into my JavaScript game?

I've created this JavaScript game: window.onload = function() { canv = document.getElementById("gc"); ctx = canv.getContext("2d"); document.addEventListener("keydown", keyPush); setInterval(game, 1000 / 7); } px = py = 10; gs = tc ...