1.0.0 • Published 6 months ago

concurrency-limit-runner v1.0.0

Weekly downloads
-
License
ISC
Repository
github
Last release
6 months ago

Concurrency Limit Runner

Run async tasks in JavaScript, limiting concurrency.

Usage

In this example, we'll fetch URLs, no more than three at a time.

import {runTasks} from 'concurrency-limit-runner';

const urls = [ /* ... */ ];
const tasks = [];
for (const url of urls) {
    tasks.push(async () => await fetch(url));
}

for await (const response of runTasks(3, tasks.values())) {
    console.log(response.status);
}

Here's another example that just sleeps, instead of fetching URLs.

import {runTasks} from 'concurrency-limit-runner';

function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

const tasks = [];
for (let i = 0; i < 20; i++) {
    tasks.push(async () => {
        console.log(`start ${i}`);
        await sleep(Math.random() * 1000);
        console.log(`end ${i}`);
        return i;
    });
}

for await (const value of runTasks(3, tasks.values())) {
    console.log(`output ${value}`);
}

Async Iterators and Generators (for await)

This library is built around async generator functions, which many JS developers may not be familiar with.

A generator function (aka function* function) returns a "generator," an iterator of results. Generator functions are allowed to use the yield keyword where you might have normally used a return keyword. The first time a caller calls next() on the generator (or uses a for...of loop), the function* function runs until it yields a value; that becomes the next() value of the iterator. But the subsequent time next() is called, the generator function resumes from the yield statement, right where it left off, even if it's in the middle of a loop. (You can also yield*, to yield all of the results of another generator function.)

An "async generator function" (async function*) is a generator function that returns an "async iterator," which is an iterator of promises. You can call for await...of on an async iterator. Async generator functions can use the await keyword, as you might do in any async function.

In the example, we call runTasks() with an array of task functions; we call .values() on the array to convert the array into an iterator.

runTasks() is an async generator function, so we can call it with a for await...of loop. Each time the loop runs, we'll process the result of the latest completed task.

1.0.0

6 months ago