Home > Software engineering >  JAVASCRIPT : Empty array after foreach loop
JAVASCRIPT : Empty array after foreach loop

Time:07-12

I'm working on a NestJSxMongoose store management project.

I have this piece of code in which I want to update some items in the database and put those updated items in an array that I will use later.

const updatedItems: Item[] = [];

purchaseData.items.forEach(async (purchasedItem) => {
  const itemInDB = await this.itemService.findItemByName(purchasedItem.name);

  itemInDB.quantity -= purchasedItem.quantity;

  const updatedItem = await this.itemService.updateItem(
    itemInDB['_id'],
    itemInDB
  );

  updatedItems.push(updatedItem);

  console.log(updatedItems); // Output : [{actual_data}]
});

console.log(updatedItems); // Output : []

The issue I have is that when I log the content of updatedItems inside the forEach(), it contains the actual expected data. But when I try to use it outside the forEach() loop, it logs an empty array. I want to use that array outside of the forEach().

What am I doing wrong ?

CodePudding user response:

If you want to wait for results, you have to write it like this: Get the array of all promises and awaits them.

.forEach (as well as .map) runs synchronously. If you pass async function as a parameter, it does not await them, it just executes them to the nearest await and then returns (still unresolved) promise.

Therefore the console.log(updatedItems); // Output : [] is executed before the logic inside async function.

const updatedItems: Item[] = [];

const promises = purchaseData.items.map(async (purchasedItem) => {
  const itemInDB = await this.itemService.findItemByName(purchasedItem.name);

  itemInDB.quantity -= purchasedItem.quantity;

  const updatedItem = await this.itemService.updateItem(
    itemInDB['_id'],
    itemInDB
  );

  updatedItems.push(updatedItem);

  console.log(updatedItems); // Output : [{actual_data}]
});

await Promise.all(promises);

console.log(updatedItems); // Output : []

Here you can see the order of execution:

const purchaseData = { items: [1,2] }

purchaseData.items.forEach(async (purchasedItem) => {
  console.log('first', purchasedItem);
  await console.log(); // the awaiting console log does nothing, it is just to trigger the heaviour of async function when it hits await
  console.log('third', purchasedItem);

  console.log(updatedItems); // Output : [{actual_data}]
});

console.log('second');

CodePudding user response:

Use Async and await its not waiting till the loop its going to next you need to wait until the loop finish

async function updateItemFun() {
const updatedItems: Item[] = [];

await purchaseData.items.forEach(async (purchasedItem) => {
  const itemInDB = await this.itemService.findItemByName(purchasedItem.name);

  itemInDB.quantity -= purchasedItem.quantity;

  const updatedItem = await this.itemService.updateItem(
    itemInDB['_id'],
    itemInDB
  );

  updatedItems.push(updatedItem);

  console.log(updatedItems); // Output : [{actual_data}]
});

console.log(updatedItems); // Output : []
}
  • Related