Problem
When I had initially seen the new syntax for for await
, my initial thought was it would behave similar to Promise.all and handle whatever was in the for loop concurrently. This is not what it does, BUT I am happy it solves asynchronous streaming.
None the less, it still did not solve this reoccurring pattern I find when developing. The need to perform many async tasks concurrently, inconveniently requires accumulating an array of promises to then be called by Promise.all.
Example Problems
Taking this as an example, you can see the requests array is now completely useless after resolving the promises, when being resolved after iteration would be more beneficial.
const requests = [];
for (const id of ids) {
requests.push(fetch(id));
}
const responses = await Promise.all(requests);
As another example, with the fetch API, there are likely more async operations to await other than the response, like parsing based on content type, this is different, but caused by the same problem of having to accumulate these promises
const requests = [];
for (const id of ids) {
requests.push(fetch(id).then(response => response.json()));
// OR
requests.push(new Promise(async (resolve) => {
const response = await fetch(id);
resolve(await response.json());
});
}
const users = await Promise.all(requests);
And in some cases, you may even want users to be a Map of id to user, which adds another layer of complexity
const users = new Map();
for (const id of ids) {
users.set(id, new Promise(async (resolve) => {
const response = await fetch(id);
resolve(await response.json());
});
}
await Promise.all(users.values());
// Now you can use users map 😖
Solution
This is where for sync
comes in, this would provide the ability to perform asynchronous operations iteratively and concurrently. Showing below as an example
const users = new Map();
for sync (const id of ids) {
const response = await fetch(id);
users.set(id, await response.json());
}