I have an array.map function that simply iterate on an array and return array of promises. Now, I’m told to change it to .reduce
instead of .map
. However, when I implemented .reduce
without changing any business logic, the time that method requires increased almost 10 times because it waits for the async calls for every element in the array.
Is there any way to use reduce to create an array of promises that will be resolved using Promise.all()
later.
I simulated almost the same case and left some of the solutions I’ve tried and the desired case in the code below.
Can somebody show me how to do it?
interface IUser { name: string; balance: number | undefined; }
let user1 = { name: 'user1', balance: undefined }
let user2 = { name: 'user2', balance: undefined }
let user3 = { name: 'user3', balance: undefined }
const users = [user1, user2, user3]
async function calculateBalance(user: IUser): Promise<IUser> {
await new Promise((resolve) => setTimeout(resolve, 5000));
user.balance = Math.floor(Math.random() * 5000) + 1000;
return user;
}
async function processUsers() {
return users.reduce(async (acc, currUser, index) => {
return [ ...acc, calculateBalance(currUser) ] // not working
return acc.push(calculateBalance(currUser)) // Argument of type 'Promise<IUser>' is not assignable to parameter of type 'never'
return acc.concat(calculateBalance(currUser)) // Same above
}, [])
}
const processedUsersArray = await processUsers();
await Promise.all(processedUsersArray) // Desired thing for the sake of performance
2
Answers
The push() method of Array instances adds the specified elements to the end of an array and returns the new length of the array.
So in your reduce you are returning a number and try to push to it.
You should be using map() not reduce and not mixing await with promise.
For the usecase you are showing a .map works perfectly fine
However if you would need to use reduce you should be able to do it like this