Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unexpected asynchronicity in NodeJS

I’m trying to search for all activities however the code appears to return an empty array of activities before it finishes searching all Course model instances with unexpected asynchronicity in the code.

const express = require("express");
const router = express.Router();

const Activity = require("../../models/Activity");
const Course = require("../../models/Course");

router.get("/:user_id", (req, res) => {
  Course.find({ subscribers: req.params.user_id })
    .then((courseList) => {
      let activities = [];
      courseList.forEach((course) =>
        Activity.find({ courseId: course._id }).then((activity) => {
          activities = [...activities, ...activity];
        })
      );

      return res.json({ activities });
    })
    .catch((err) => res.status(404).json({ nocoursefound: "No Course found" }));
});

module.exports = router;

when I change the return line to return setTimeout(() => res.json({ activities }),500) I get the list of activities I’m searching for. I want to remove the setTimeout function and to successfully retrieve the activities list.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Looks like the issue is that the Course.find method is asynchronous, meaning that it returns immediately without waiting for the search to complete. This means that the res.json method is called before the activity array has been populated with the results of the search.

One way to fix this issue would be to use the Promise.all method, which allows you to wait for multiple promises to complete before continuing with the rest of the code. You can use this method to wait for all of the Activity.find promises to complete before calling res.json.

Here’s an example of how you could modify your code to use Promise.all:

router.get("/:user_id", (req, res) => {
  Course.find({ subscribers: req.params.user_id })
    .then((courseList) => {
      let activityPromises = [];
      courseList.forEach((course) => {
        activityPromises.push(Activity.find({ courseId: course._id }));
      });

      return Promise.all(activityPromises);
    })
    .then((activityLists) => {
      // Flatten the array of arrays into a single array
      let activities = [].concat.apply([], activityLists);
      return res.json({ activities });
    })
    .catch((err) => res.status(404).json({ nocoursefound: "No Course found" }));
});

This code uses the Promise.all method to wait for all of the Activity.find promises to complete before calling res.json.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading