0

Good day, Not gonna beat around the bush, I think my issue is simple. I have a function to get the total cost of a transaction. There's a forEach (for each item the user wants to buy). Here is what I have right now:

async function getTotalCost(ListOfItems) {
    return new Promise ((resolve, reject) => {
        var totalcost = 0;
        ListOfItems.forEach( async (market_hash_name, index) => {
            var cost = await Price.findOne({ market_hash_name: market_hash_name });
            if (cost == null) {return reject("item cost not found")}
            cost = cost.price
            console.log("DEBUG - cost:",market_hash_name,cost)
            totalcost = totalcost + cost
            if (index === ListOfItems.length -1) {
                console.log('DEBUG - totalcost:',totalcost)
                resolve(totalcost)
            }
        });
    })
}

I searched on stack overflow for people with similar questions and came across this: Best way to wait for .forEach() to complete . As you can probably tell I emloyed the solution proposed. However I find it only delayed the problem, here is a log:

DEBUG - cost: Sealed Graffiti | Keep the Change (Battle Green) 3
DEBUG - cost: Sealed Graffiti | Eco (Frog Green) 3
DEBUG - cost: Sealed Graffiti | Sorry (Desert Amber) 3
DEBUG - cost: Sealed Graffiti | QQ (Cash Green) 3
DEBUG - totalcost: 12
STEAM BOT - item being sent to user
STEAM BOT - pending
DEBUG - cost: Sealed Graffiti | Speechless (Violent Violet) 3
DEBUG - cost: Sealed Graffiti | Toasted (Tiger Orange) 3
DEBUG - totalcost: 6
DEBUG - cost: Sealed Graffiti | Backstab (Shark White) 3
DEBUG - cost: Sealed Graffiti | Keep the Change (Frog Green) 3

Any suggestions? I could probably fix this in some really convoluted way, but I would prefer a more efficient solution to what I could probably scrape up.

Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
Bob Boby
  • 183
  • 8

1 Answers1

2

forEach is not promise-aware. It cannot support async and await. You cannot use await in forEach.

To wait the result we should return back to old-school “for loop”, but this time you can use modern version with for..of construction (thanks to Iteration Protocol) for better readability:

async function processArray() {
   for (const item of array) {
      await delayedLog(item);
}
}

Process array in parallel

async function processArrayInPArallel() {
     const promises = array.map(delayedLog);
      await Promise.all(promises);

}
Navitas28
  • 745
  • 4
  • 13
  • Thanks! I'm not gonna hide the fact that I'm still learning about javascript, so I didn't even know about for of loops! Solved the problem perfectly! – Bob Boby Aug 08 '20 at 12:49