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);
})();
- 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);
- })();
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 = 0
1
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);
})();
- //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);
- })();
//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:
1
2
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);
})();
- //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);
- })();
//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