Created
February 14, 2024 23:47
-
-
Save dheniges/ebfae6654c93b5f26be32ba466d4a28f to your computer and use it in GitHub Desktop.
A small node.js module to allow concurrent processing of any AsyncIterator via AsyncGenerator
This file contains hidden or 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
import { randomUUID } from 'crypto' | |
// A concurrency-limited pool of promises generated from any async iterable compatible feed. | |
// A processor function is required to take the result of the async iteration and return a value. | |
// Processor func can be async | |
// | |
// Will only run [concurrency] operations at once | |
// The pool will fill as fast as the async iteration function can provide values, up to the max concurrency | |
export default async function* asyncPool(concurrency: number, itemFeed: AsyncIterable<any>, iteratorFn: (...args : any[]) => any) { | |
const promiseMap = new Map() | |
async function completePromise() { | |
const [id, value] = await Promise.race(promiseMap.values()) | |
promiseMap.delete(id) | |
return value | |
} | |
for await (const item of itemFeed) { | |
const id = randomUUID() // Assign a random id to the promise | |
const promise: any = Promise.all([id, iteratorFn(item)]) | |
promiseMap.set(id, promise) | |
if (promiseMap.size >= concurrency) { | |
yield await completePromise() | |
} | |
} | |
// Finish any remaining promises still running | |
while (promiseMap.size) { | |
yield await completePromise() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example usage: