Reputation: 724
I have large array of objects and filtered the objects based on the userID. Here is the code below.
const filteredArr = LargeArr.Items.reduce(
async(acc, { attributes: { dob, name, picture} = { dob: null, name: null, picture: null }, userID }) => {
let pic = null;
if (picture) { pic = await getPic(picture); } // async here
acc[userID] = { name, userID, pic, dob };
return acc;
}, {});
Expected Output :
{
'1595232114269': {
name: 'Mark Status',
userID: '1595232114269',
picture: 'mark-status.jpg',
dob: '2020-08-10'
},
'48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d23d': {
name: 'Jack Thomas',
userID: '48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d23d',
picture: 'jack-thomas.jpg',
dob: '1990-12-20'
},
'48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d47p': {
name: 'Petro Huge',
userID: '48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d47p',
picture: 'petro huge.jpg',
dob: '1856-12-20'
},
'48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d55j': {
name: 'Mark Henry',
userID: '48e69555d778f9b9a3a1d553b9c3b8f7dd6a3394ac82df1433b60a69c055d55j',
picture: 'mark-henry.jpg',
dob: '2005-12-29'
}
}
I need to get picture from an api which is asynchronous, so used async await inside the reduce method. The problem here is it is always showing as Promise pending. If this was an array of object, then i can return Promise.all, but since this is object containing object how can i proceed with this inside reduce method? I need the exact same expected output.
Can somebody help me with this? Any help would be really appreciated.
Upvotes: 0
Views: 455
Reputation: 370789
To use reduce
while iterating over items asynchronously, you'd have to have the accumulator which gets passed from callback to callback to be a Promise. While this is possible, it'll make things pretty difficult to read, and introduces some unnecessary syntax noise.
Use a plain for
loop instead:
const filteredArr = {};
for (const item of LargeArr.Items) {
const { attributes: { dob, name, picture} = { dob: null, name: null, picture: null } } = item;
const pic = picture ? await getPic(picture) : null;
filteredArr[userID] = { name, uesrID, pic, dob };
}
If you really wanted to take the reduce
route:
LargeArr.Items.reduce(
(acc, { attributes: { dob, name, picture} = { dob: null, name: null, picture: null }, userID }) => {
return acc.then(async (acc) => {
let pic = null;
if (picture) { pic = await getPic(picture); } // async here
acc[userID] = { name, userID, pic, dob };
return acc;
});
}, Promise.resolve({})
)
.then((filteredArr) => {
// do stuff with filteredArr
});
Unless the getPic
calls need to be made in serial, you could consider using Promise.all
instead, to iterate through the whole array at once, rather than waiting on the resolution of the prior Promise before going onto the next.
If your API can handle Promise.all
:
const filteredArr = {};
await Promise.all(LargeArr.Items.map(async (item) => {
const { attributes: { dob, name, picture} = { dob: null, name: null, picture: null } } = item;
const pic = picture ? await getPic(picture) : null;
filteredArr[userID] = { name, uesrID, pic, dob };
}));
Upvotes: 1