Anurag
Anurag

Reputation: 307

NodeJs API responding with incomplete object

I am trying to implement API using NodeJs that reads data from database collection and again form that data reads respective data from another collection and updating same object with new key value pairs.

The objects are updating successfully but the API response that I recieve on Frontend is not updated with second collection values.

router.get('/exam/:_id' , (req , res) => {
    ExamModel.find({
        userId: req.params._id
    })
        .then(doc => {
            let i=0;
            for(let data of doc){
                i=i+1;
                ResponseModel.find({examId: data._id}).countDocuments()
                   .then(count=>{
                        data.responseCount= count;
                        if(i===doc.length){
                           res.json(doc)
                        }
                    })
                    .catch(err => {
                        res.status(500).json(err)
                    })

            }
        })
        .catch(err => {
            res.status(500).json(err)
        })
})

The object recieved from ExamModel is

[
    {
        _id: "012",
        responseCount: 0,
        data: [array]
    },
    {
        _id: "015",
        responseCount: 0,
        data: [array]
    }
]

after ResponseModel the object become

[
    {
        _id: "012",
        responseCount: 5,
        data: [array]
    },
    {
        _id: "015",
        responseCount: 2,
        data: [array]
    }
]

But as a response of api, I am getting the first object not second.

And also I am getting error

(node:15012) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:470:11)

Upvotes: 1

Views: 325

Answers (1)

vishnu
vishnu

Reputation: 2011

The doc object returned by the query will be in an immutable state. In order to modify the object, you need to convert it to a plain javascript object first.

You can perform the below operation before the for loop.

const result = doc.map(d => d.toObject());

Now you can use the result object in you for loop and make modification the result object.

Regarding the ERR_HTTP_HEADERS_SENT error. The for loop will complete the iteration long before the count query returns the promise. This will make the if(i===doc.length) condition true multiple times.

You can use async/await function as below in order to solve the issue

router.get("/exam/:_id", async (req, res) => {
  try {
    const doc = await ExamModel.find({ userId: req.params._id });
    const result = doc.map((d) => d.toObject());
    for (let data of result) {
      const count = await ResponseModel.countDocuments({ examId: data._id });
      data.responseCount = count;
    }
    res.json(result);
  } catch (err) {
    console.log(err);
    res.status(500).json({ message: "Interval Server Err" });
  }
});

Upvotes: 3

Related Questions