Let's say I have an async/await that calls an API that fetches all users.
async function getUsers() {
const users = await Api.getAllUsers()
return users.map(user => {
return {
id: user.id,
group: 'data depends on subsequent API call',
}
})
}
Within the return map, I have to do another API call to get some data that should be in the same scope.
const groupByUser = Api.getGroupByUserId()
How do I accomplish this? Can I put an async/await within the existing one? Do I create an array of all users ids and somehow map through that? I'm kind of lost on where to go next and any input would be appreciated.
// getUsers() passed into componentDidMount() wrapper
Use an async
function for your map function and then use Promise.all
on that result.
async function getUsers() {
const users = await Api.getAllUsers()
return Promise.all(users.map(async (user) => {
return {
id: user.id,
group: await Api.getGroupByUserId(user.id),
}
}))
}
When you map
with an async function you essentially get an array of promises. That's why you need Promise.all
As long as you are using async/await you can continue to await in your getUsers
function. You can reduce the list of users to an async function which will build a self executing async function to await. This function will build the new array.
// MOCK Api
const Api = {
getAllUsers: async () => [{name: 'user1', id: 1}, {name: 'user2', id: 2}],
getGroupByUserId: async (id) =>
new Promise(resolve => setTimeout(() => resolve('users'), id*1000)),
};
// End MOCK Api
async function getUsers() {
const users = await Api.getAllUsers()
return await users.reduce((list, user) => {
return async () => {
$nextList = await list()
$nextList.push({
id: user.id,
group: await Api.getGroupByUserId(user.id)
})
return $nextList
}
}, async () => [])()
}
(async () => {
const allUserGroups = await getUsers();
console.log(allUserGroups);
})();
// 3s -> [ { id: 1, group: 'users' }, { id: 2, group: 'users' } ]
Edit: On a side note this method makes sure that API requests happen in series, so it is a little easier on the API as far as load, but will be a slower. If you want all of the API requests to happen as soon as possible, the method using Promise.all and map will be a faster since it will make all of the API calls in parallel. ALL, so don't use that method for large lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With