In MongoDB using Express, how can I ensure that a code is only executed after all queries inside a loop have been completed?

Here's a snippet of code from my router:

router.get('/questions/best', function(req, res, next) {
    Question.aggregate([
        // Include data protection measures with $ifNull and max[$size,1]       
        {$project: {ratio: {$divide:[
            {$arrayElemAt:[{$ifNull:["$likes",[0]]}, 0]},
            {$max:[1, {$arrayElemAt:[{$ifNull:["$dislikes",[0]]}, 0]}]}
        ]}},
        {$sort: {ratio: -1}},
        {$limit: 15}
    ]).exec(function(err, results) {
        if (err) {return next(err)}
        
        let top15 = [];
        for(let i = 0; i < results.length; i++) {
            Question.findOne({_id: results[i]._id}).exec(function(err, result) {
                if (err) {return next(err)}
                top15.push(result);
                
                if (top15.length === results.length) {
                    res.render('content', { whichOne: 5, user: req.user, questions: top15 });
                }
            })
        }
    });
});

I'm facing an issue where the template gets rendered automatically before all queries are completed, causing incomplete data to be displayed. I've tried using setTimeout but it's not reliable due to varying processing times. Is there a way to ensure that the template is rendered only after all queries have returned and their values are populated in the array? Any suggestions or help would be greatly appreciated. Thank you!

Answer №1

After going through the mongoose documentation, it became clear that using promises for handling asynchronous operations is quite straightforward.

Implementing Promises:

router.get('/questions/best', (req,res,next) => {
    Question.aggregate([
        // Handle potential missing fields with $ifNull                                                         
        // Prevent division by zero dislikes using max[1,size]                                         
        {$project: {ratio: {$divide:[
        {$arrayElemAt:[{$ifNull:["$likes",[0]]}, 0]},
            {$max:[1, {$arrayElemAt:[{$ifNull:["$dislikes",[0]]}, 0]}]}
            ]}
        }},
        {$sort: {ratio:-1}},
        {$limit: 15}
    ]).exec()
    .then(results => Promise.all(results.map(({_id}) => Question.findOne({_id}).exec())))
    .then(questions => res.render('content', { whichOne: 5, user: req.user, questions}))
    .catch(next);
});

Alternatively, utilizing async/await:

router.get('/questions/best', async (req,res,next) => {
    try {
        const results = await Question.aggregate([
            // Handle potential missing fields with $ifNull                                                         
            // Prevent division by zero dislikes using max[1,size]                                         
            {$project: {ratio: {$divide:[
            {$arrayElemAt:[{$ifNull:["$likes",[0]]}, 0]},
                {$max:[1, {$arrayElemAt:[{$ifNull:["$dislikes",[0]]}, 0]}]}
                ]}
            }},
            {$sort: {ratio:-1}},
            {$limit: 15}
        ]).exec();
        const questions = await Promise.all(results.map(({_id}) => Question.findOne({_id}).exec()));
        res.render('content', { whichOne: 5, user: req.user, questions});
    } catch(err) {
        next(err);
    }
});

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

JavaScript event/Rails app encounters surprising outcome

I have encountered a strange bug in my JavaScript code. When I translate the page to another language by clicking on "English | Русский" using simple I18n translation, my menu buttons stop working until I reload the page. I suspect that the issue ...

Plane flying above a Box in ThreeJs

Encountering an issue where a plane placed over a box disappears at certain camera angles. It seems like the problem is related to the box's polygons, but the exact cause is unknown. You can view an example here: http://jsfiddle.net/fv9sqsoj/9/ var ...

Buttons for displaying and concealing content are unresponsive

After spending over 6 hours trying to fix this code and searching online, I am completely frustrated. My goal is to hide the login table and its associated background image (#lg #ck) and instead, place a button on top of where the login table is. When thi ...

Experiencing difficulty establishing connection with server while working in ReactJS

When attempting to run the setup, I encountered the following error: npm run setup **Sequelize CLI [Node: 12.14.1, CLI: 5.5.1, ORM: 5.21.6] Loaded configuration file "src\config\database.json". Using environment "development" ...

Exploring Several Images and Videos in Angular

I'm experiencing a challenge with displaying multiple images and videos in my Angular application. To differentiate between the two types of files, I use the "format" variable. Check out Stackblitz export class AppComponent { urls; format; on ...

"Chrome is throwing an unanticipated error for bigpipe.js with an uncaught syntax error related to

I have integrated the bigpipe.js method into my website to display a newsfeed. It functions properly on all browsers except for Google Chrome, where it shows an 'uncaught syntaxerror unexpected token =' error. I need assistance in resolving this ...

Sending information using AJAX to interact with a PHP script

My input field is set up to receive multiple files: <input id="propertyImages" type="file" name="submission_img[]" multiple accept=".jpg, .jpeg, .png, .gif"/> Afterwards, I send this data via JS/Ajax to a PHP file: //Creating the form data to be s ...

Conceal or reveal form elements based on input selection

In my current HTML form generated by PHP, I have multiple instances of the following structure: function show(elem, show){ var elements = elem.parentNode.parentNode.parentNode.getElementsByClassName("hidden"); var i; for(i=0; i<eleme ...

Dynamically adding a CSS gradient to an element with JQuery

Check out my HSL color picker on JS Bin I have created a simple HSL color picker that dynamically applies a gradient to a range input type upon DOM ready and changes to update the picker. // Code Update Setup $(".cpick-code-hsl").on('change keyup&ap ...

Gathering information for creating and organizing concurrent Airflow tasks

My Airflow application is designed to run a model for various entities. Originally, the model operated in three stages within an Airflow DAG, with each stage calculating attributes for each entity one after the other. The process was not efficient as it to ...

Passing the variable that contains the size of the table from JavaScript to PHP

Currently, I have a PHP page that consists of the following code: $sizelimit = "6"; include ('table.php'); This setup functions well by displaying the last 6 MySQL entries from my table generated by PHP on the main page and displays either the ...

Exploring the inner workings of an Object by accessing its array

In my functional component, I'm rendering the values of an object. const MovieItemDetails = (props) => { return <div className='item-details'> <div> <img key={props.movieDetails.id} src={`https://image.tmdb ...

What is the best way to integrate Emotion styled components with TypeScript in a React project?

Currently, I am delving into TypeScript and attempting to convert a small project that utilizes Emotion to TypeScript. I have hit a roadblock at this juncture. The code snippet below export const Title = styled.div(props => ({ fontSize: "20px", ...

Can you explain the distinction between res.send and res.write in the Express framework?

As someone who is new to express.js, I am currently exploring the distinctions between res.send and res.write. Can anyone provide some insight into this? ...

Learn the process of dynamically populating an HTML table with data using JavaScript and JSON

I have developed a code snippet to dynamically add an HTML table without using jQuery. The code serves as an application from the server to the client, where the client receives a JSON object to parse into a string. Here is how you can add an HTML table ...

Tips for creating a new route within a separate component in React JS without causing the previous one to unmount

I am currently developing a recipe website using React JS and React Router. On the HomePage, I have set up a display of cards, each representing a preview of a recipe. Each card is enclosed within a <Link></link> tag. When one of these cards ...

Error: React unable to locate module './WebpackMissingModule'

Recently I started diving into React, and I'm encountering some difficulties trying to export components. Here is my current index.js file setup: import React from 'react'; import ReactDOM from 'react-dom'; import SearchBar from ...

What could be causing the issue with the unexpected token in the API Ajax request?

I have a document that contains the following content: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8> <title>Document</title> </head> <body> <script src="http://ajax.aspnetcdn.com/ ...

Encasing the app component with a context and encountering the issue: TypeError - (destructured parameter) does not have a defined value

My goal is to wrap all components under the app in a context to provide specific functionalities (as evidenced by my UserContext component). import React, { useState, createContext, useContext } from 'react' const Context = createContext(); exp ...

Why is it that my JQuery sliders appear perfectly fine when viewed locally, but fail to show up when accessed on

I'm facing an issue with two JQuery sliders on my page. The local version works fine, but when I upload it to my web host, only one slider functions correctly. I need both of them to work as intended. Any insights on how to resolve this problem? See ...