Devang Mukherjee
Devang Mukherjee

Reputation: 197

Unable to use async in forEach loop inside an API call

I have a get API call which looks like this

router.get('/review', async (req, res) => {
  try {
    const entity = await Entity.find();
    const entityId = [];
    Object.keys(entity).forEach((key) => {
      entityId.push(entity[key]._id);
    });
    const results = [];
    Object.keys(entityId).forEach(async (key) => {
      const reviews = await Review.find({ entityId: entityId[key] });
      results.push(reviews);
    });

    res.send(results);
  } catch (e) {
    res.status(500).send();
  }
});

In entityId array it has a list of all the id i need and till there it works. Now what I want to do is iterate over each id of entityId and find the corresponding review that the entity has, push those review into a results array and return results.

review has an entityId field which is same as id of entity.

I also looked at - Using async/await with a forEach loop

which suggested to use for loop but it gave the following error.

iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.eslintno-restricted-syntax

How can I solve this?

Upvotes: 0

Views: 248

Answers (2)

Thisara Senanayake
Thisara Senanayake

Reputation: 26

use promises instead of foreach.

Thy this

const data = async () => {
  const entity = {
    a: { _id: "1231" },
    b: { _id: "1232" },
    c: { _id: "1233" }
  };

  const entityId = [];
  Object.keys(entity).forEach(key => {
    entityId.push(entity[key]._id);
  });
  const promise = [];
  Object.keys(entityId).forEach(async key => {
    const reviews = Review({ entityId: entityId[key] });
    promise.push(reviews);
  });
  const results = await Promise.all(promise);
};

const Review = (option) => {
  return true;
};

data();

Upvotes: 1

Eray Ismailov
Eray Ismailov

Reputation: 305

forEach does not respect await therefore it may result in unintentional behaviour you can use map to return array of promises from Review.find() and wrap those in await Promise.all({promises array here}) and use await on Promise.all. This will result in parallel calls instead of doing them sequentially one after another.

const promisesWoAwait = this.entityIds.map(entityId => Review.find({ entityId }));

const result = await Promise.all(promisesWoAwait);

Upvotes: 2

Related Questions