Home > Enterprise >  Use async await in forEach loop, node js
Use async await in forEach loop, node js

Time:07-16

I had a problem when I tried to use forEach that contained await inside the loop, so I need to define the async in front of the forEach loop and it returned the error.

exports.filterAverageRatingsEachSkillForStudent = async (req, res) => {
  let receiver = req.query.receiver;
  let result = [];
  try {
    console.log('receiver id', receiver);

    for (let id of receiver) {
      console.log('Query String ', id);
      const findRating = await FeedbackSchema.find({
        receiver: id,
        //will add level query later
      }).select('ratingL ratingS ratingR ratingW');
      console.log('Rating Length', findRating.length);
      let totalSpeaking = 0;
      let totalWriting = 0;
      let totalListening = 0;
      let totalReading = 0;
      let lengthS = findRating.length;
      let lengthR = findRating.length;
      let lengthL = findRating.length;
      let lengthW = findRating.length;

      findRating.forEach((rating) => {
        console.log('Speaking star = ', rating.ratingS);
        totalSpeaking  = rating.ratingS;
      });
      console.log('Total speaking', totalSpeaking);
      console.log('lengthS = ', lengthS);
      let highestS = lengthS * 5;
      let resultOfSpeakingRate = (totalSpeaking * 5) / highestS;
      console.log('Average Speaking Rate ---> ', resultOfSpeakingRate);

      findRating.forEach((rating) => {
        totalWriting  = rating.ratingW;
      });
      let highestW = lengthW * 5;
      let resultOfWritingRate = (totalWriting * 5) / highestW;

      findRating.forEach((rating) => {
        totalReading  = rating.ratingR;
      });
      let highestR = lengthR * 5;
      let resultOfReadingRate = (totalReading * 5) / highestR;

      findRating.forEach((rating) => {
        totalListening  = rating.ratingL;
      });
      let highestL = lengthL * 5;
      let resultOfListeningRate = (totalListening * 5) / highestL;
      
      res.json({
        writing: resultOfWritingRate,
        speaking: resultOfSpeakingRate,
        listening: resultOfListeningRate,
        reading: resultOfReadingRate,
      });
    }
    //return res.json(totalRating);
  } catch (error) {
    console.log(error.message);
  }
};

Error, able to solve the async await error but still return me only one response result and after that, it showed cannot sent header

enter image description here enter image description here

CodePudding user response:

.forEach() is not async-aware. Use a plain for/of loop instead. In fact, pretty much stop using .forEach() entirely these days as its basically obsolete. With block scope available now with let and const, there is no reason to use .forEach() and it's extra function scope any more. Use a regular for loop instead.

You can fix this particular code by changing to this:

exports.filterAverageRatingsEachSkillForStudent = async (req, res) => {
    let receiver = req.query.receiver; //array of id ['ABBd23', 'SDSd242', 'dfNJ47']
    try {
        console.log('receiver id', receiver);

        for (let id of reciever) {
            console.log('Query String ', id);
            const findRating = await FeedbackSchema.find({
                receiver: id,
            }).select('ratingL ratingS ratingR ratingW');
        }
    } catch (error) {
        console.log(error.message);
    }
}

It also appears that you must not have disclosed all the code for this function because it looks like you're trying to get findRating, but then you never do anything with it.

The error you report about cannot set headers after they are sent does not occur in this code since that error is about sending multiple responses to the same incoming request and you don't send any responses in this code. So, help with that particular error would require disclosing more code or perhaps fixing this function will also fix that (we can't tell since we can't see the code that actually causes that error).

CodePudding user response:

You can also make use of Promise.all() if there is no dependency between each iteration. Here is the example -

exports.filterAverageRatingsEachSkillForStudent = async (req, res) => {
  let receiver = req.query.receiver; //array of id ['ABBd23', 'SDSd242', 'dfNJ47']
  try {
    console.log('receiver id', receiver);
    let results = await Promise.all(receiver.map(async (id) => {
      console.log('Query String ', id);
      return FeedbackSchema.find({
        receiver: id,
      }).select('ratingL ratingS ratingR ratingW'); 
   });
   console.log(results) // this will be an array of results
 } catch (error) {
    console.log(error.message);
  }
  • Related