Recently I discovered that Array.prototype.forEach() function is not suitable for 'awaitable' functions. Let's have a look at an example.
const getAsyncData = (n) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(n), 500) }) }; const arr = [1,2,3,4,5]; //forEach example (async () => { let total = 0; arr.forEach(async n => { let res = await getAsyncData(n); console.log(res); total += res; }); console.log('total = ' + total); })();
I expected that forEach will await for every call of the getAsyncData() function so that to calculate total correctly, but surprisingly the result was different.
total = 01
2
3
4
5
Obviously, forEach ignores await keyword and quits immediately so total is not calculated.
To make await working properly I replaced forEach with for .. of
//for of example (async () => { let total = 0; for (let n of arr){ let res = await getAsyncData(n); console.log(res); total += res; } console.log('total = ' + total); })();
That approach gives expected result:
12
3
4
5
total = 15
Alternatively, we can also use Promise.all function if processing order does not matter
//Promise.all example (async () => { let total = 0; total = await Promise.all(arr.map(n => getAsyncData(n))) .then(results => results.reduce((acc, el) => acc + el)); console.log('total = ' + total); })();
No comments:
Post a Comment