Reputation: 1775
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
Upvotes: 7
Views: 4571
Reputation: 404
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.
Upvotes: 2
Reputation: 14423
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
Upvotes: 11