Javascripts async and loops
Norman
Posted on May 5, 2020
Thanks to async/await many pieces of code became much more declarative. But there is one tricky scenario that I just bumped into: I needed to do a handful of API requests in a loop and refresh the list view afterwards. Easy peasy?
async updateAllItems (listOfItems) {
listOfItems.forEach(async (item) => {
await collection.updateItem(item.id, { status: 'coolNewStatus' })
})
const newItems = await collection.allItems()
return newItems
}
What's the problem here? Some people might have seen it already (unlike me in the last couple of hours): newItems will be loaded before the loop ended because we're not actually waiting for it to end. Simply throwing another await
in front of it doesn't cut it either.
There are at least three possible solutions, depending on your style.
ā
Sticking to the procedural approach:
async updateAllItems (listOfItems) {
for (const item of listOfItems) {
await collection.updateItem(item.id, { status: 'coolNewStatus' })
}
const newItems = await collection.allItems()
return newItems
}
Why are people so afraid of for-loops anyway?
ā
Promise.all
async updateAllItems (listOfItems) {
await Promise.all(listOfItems.map(item => {
return collection.updateItem(item.id, { status: 'coolNewStatus' })
}))
const newItems = await collection.allItems()
return newItems
}
A little lispy, isn't it?
ā await async
async updateAllItems (listOfItems) {
listOfItems.forEach(await (async (item) => {
await collection.updateItem(item.id, { status: 'coolNewStatus' })
}))
const newItems = await collection.allItems()
return newItems
}
This does NOT work. Why? No idea. Do you have any idea?
Anyways, I hope this helps you with your next async race condition. Cheers š„
Posted on May 5, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.