You should compare it with:
private async loadImages(urls: string[]): Promise<void> {
for(url of urls) {
await this.loadImage(url);
}
}
that call really does wait for each promise to succeed before starting the next and should be far worse in total time to completion.
In a more general sense: You cannot gain infinite concurrency. JavaScript is single-threaded and starting 100 requests in parallel may in fact make your code slower as you have too many requests open at the same time. (You may end up doing a denial of service attack without even realizing it.)
It may make sense to chunk your urls in a set of 5 or 10 urls, and do a Promise.all
on each chunk. (Or use a Promise libary where you can set the concurrency like Bluebird).
I did a testcase but bear in mind that I was using nodejs and not a browser so your mileage may vary. I compared the all in parallel, the iterative and a chunked approach. The all-in-parallel was by far the fastest:
- parallel: 345.985ms
- chunked: 1633.872ms
- iterative: 6681.045ms
Here's my code:
import fetch from 'node-fetch';
const parallel = async (urls: string[]): Promise<void> => {
await Promise.all(
urls.map(async (url) => {
return fetch(url);
})
);
}
const chunk = <T>(array: T[], size: number = 5): T[][] =>
Array.from({length: Math.ceil(array.length / size)}, (value, index) => array.slice(index * size, index * size + size));
const chunked = async (urls: string[]): Promise<void> => {
const chunkedUrls = chunk(urls);
for (const chunk of chunkedUrls) {
await Promise.all(chunk.map(url => fetch(url)));
}
}
const iterative = async (urls: string[]): Promise<void> => {
for (const url of urls) {
await fetch(url);
}
}
const compare = async () => {
const urls = [...Array(100)].map(() => `http://placekitten.com`);
console.time('parallel');
await parallel(urls);
console.timeEnd('parallel');
console.time('chunked');
await chunked(urls);
console.timeEnd('chunked');
console.time('iterative');
await iterative(urls);
console.timeEnd('iterative')
return 'completed';
}
compare()
.then(console.log)
.catch(console.error);