I want to use await Promise.all
with axios so that the requests can be sent concurrently. I have a map with the key as an id, and the value as an url. I want to retain the output also in a similar map, the key would still be the id but the value would be the response (arraybuffer).
Following is what I got suggested by a LLM:
async function fetchImages(
idUrlMap: Map<string, string>
): Promise<Map<string, ArrayBuffer>> {
// Convert the map into an array of promises
const promises = Array.from(idUrlMap.entries()).map(([id, url]) => {
return axios
.get(url, { responseType: 'arraybuffer' })
.then(response => ({ id, data: response.data }));
});
// Resolve all promises concurrently
const results = await Promise.all(promises);
// Convert the results back into a map
const resultMap = new Map<string, ArrayBuffer>();
results.forEach(({ id, data }) => {
resultMap.set(id, data);
});
return resultMap;
}
What I'm wondering is -- we are doing axios.get().then() for each array element, which will resolve the promise as soon as it's ready. So the promises won't actually get aggregated and get resolved at Promise.all
. Hence I won't achieve concurrency.
Is my understanding correct? Why/why not?
I would suggest you run the following code to see the behavior yourself:
async function fetchImages(idUrlMap) {
// Convert the map into an array of promises
const promises = Array.from(idUrlMap.entries()).map(([id, url]) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(id, 'Triggered timeout');
resolve();
}, 3000-id*1000)
}).then(() => {
console.log('In then for', id);
return { id }
})
});
// Resolve all promises concurrently
const results = await Promise.all(promises);
console.log('Results finished', results);
}
fetchImages(Object.entries({'1': 'test1', '2': 'test2', '3': 'test3'}));
This is a simplified version of yours which uses setTimeout
instead of axios
, but the same principle applies. You'll notice that results
ends up being an array of the value returned in your then
callback. In other words, it all runs as you would expect, no overthinking required.
Expected output:
2 Triggered timeout
In then for 2
1 Triggered timeout
In then for 1
0 Triggered timeout
In then for 0
Results finished [ { id: 0 }, { id: 1 }, { id: 2 } ]