walrisus
walrisus

Reputation: 89

Is it possible to wait for inner `await` before continuing?

I'm writing a function that calculates the total $ amount by querying the database to get the price, and then multiplying it by the quantity. It does this for every item in the array and pushes the total to an array which is then reduced to one final total number which is returned. The function is shown below:

const calculateOrderAmount = async (items: cartProduct[]): Promise<number> => {
  const priceArray: number[] = [];
  items.forEach(async (p: cartProduct) => {
    const product = await Product.findById(p.prodId).exec();
    if (product) {
      const totalPrice = product.price * p.quantity;
      priceArray.push(totalPrice)
    } else return; 
  });
  let amount;
  if (priceArray.length === 0) amount = 0;
  else amount = priceArray.reduce((a, b) => a + b);
  return amount;
};

The problem that I'm having is with the asynchronicity of it. I want it to wait for the forEach to finish, but since it's asynchronous, it keeps going and does the rest of the function first, so it end up returning 0. Is there a way to make it wait for the forEach to finish? Or should I rewrite it in a different way

Upvotes: 1

Views: 198

Answers (2)

trincot
trincot

Reputation: 350137

By using a forEach callback, you create a separate series of promises, but the forEach call itself will not await those promises.

The simple solution is to use a for loop, which does not use a callback system:

for (let p: cartProduct of items) {
    const product = await Product.findById(p.prodId).exec();
    if (!product) continue;
    const totalPrice = product.price * p.quantity;
    priceArray.push(totalPrice);
}

Upvotes: 1

old greg
old greg

Reputation: 897

You can try the for await of construct:

for await (variable of iterable) {
 statement
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of

Upvotes: 3

Related Questions