Limited parallelism with async/await in Typescript/ES7

Psst, there’s a package that does this for you on npm called p-map


Promise.all will allow you to wait for all requests to stop finishing, without blocking their creation.

However, it does sound like you want to block sometimes. Specifically, it sounded like you wanted to throttle the number of requests in flight at any given time. Here’s something I whipped up (but haven’t fully tested!)

async function asyncThrottledMap<T, U>(maxCount: number, array: T[], f: (x: T) => Promise<U>) {
    let inFlight = new Set<Promise<U>>();
    const result: Promise<U>[] = [];

    // Sequentially add a Promise for each operation.
    for (let elem of array) {

        // Wait for any one of the promises to complete if there are too many running.
        if (inFlight.size >= maxCount) {
            await Promise.race(inFlight);
        }

        // This is the Promise that the user originally passed us back.
        const origPromise = f(elem);
        // This is a Promise that adds/removes from the set of in-flight promises.
        const handledPromise = wrap(origPromise);
        result.push(handledPromise);
    }

    return Promise.all(result);

    async function wrap(p: Promise<U>) {
        inFlight.add(p);
        const result = await p;
        inFlight.delete(p);
        return result;
    }
}

Above, inFlight is a set of operations that are currently taking place.

The result is an array of wrapped Promises. Each of those wrapped promises basically adds or removes operations from the set of inFlight operations. If there are too many in-flight operations, then this uses Promise.race for any one of the in-flight operations to complete.

Hopefully that helps.

Leave a Comment