Created
April 9, 2024 18:21
-
-
Save Chudesnov/55d4691824cac5fc9df2c29f60298c7c to your computer and use it in GitHub Desktop.
Fetch all urls as fast as possible, limited by concurrency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Fetch all urls as fast as possible. | |
* Concurrency limits the amount of simultaneous window.fetch calls. | |
* Return fetched results in preserved order. | |
*/ | |
export async function fetchAll<T>(urls: string[], concurrency: number = 3): Promise<T[]> { | |
const results: T[] = []; | |
const pool: Set<Promise<T>> = new Set(); | |
let next: () => void = () => {}; | |
let _finish: () => void = () => {}; | |
const done = new Promise<void>((resolve) => { | |
_finish = resolve; | |
}); | |
const waitForSlot = () => | |
new Promise<void>((resolve) => { | |
next = resolve; | |
}); | |
async function* queue() { | |
for (let index = 0; index < urls.length; ) { | |
if (pool.size < concurrency) { | |
yield [urls[index], index] as const; | |
index++; | |
} else { | |
console.log("Waiting for open slot"); | |
await waitForSlot(); | |
} | |
} | |
console.log("All requests queued"); | |
next = () => { | |
if (pool.size === 0) { | |
console.log("All requests finished!"); | |
_finish(); | |
} | |
}; | |
} | |
for await (const [url, index] of queue()) { | |
console.log(`loading ${url}`); | |
const request = fetch(url).then<T>((response) => response.json()); | |
pool.add(request); | |
console.time(`loaded ${url}`); | |
request.then((result) => { | |
console.timeEnd(`loaded ${url}`); | |
results[index] = result; | |
pool.delete(request); | |
next(); | |
}); | |
} | |
await done; | |
return results; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment