0.0.6 • Published 5 years ago

awaitn v0.0.6

Weekly downloads
2
License
MIT
Repository
-
Last release
5 years ago

This is alpha quality, needs more tests.

Provides:

async function awaitn(n, generator, [onResolve, onReject, maxPerPeriod, timePeriodInMilliseconds])

Takes a generator the produces promises and windows at most N to be waited on calling onResolve and onReject for each promise. If either of onResolve or onRejected return a value awaitn will resolve to that value and stop.

This is mainly useful for limiting async code that talks to other services to ensure at most n conversations are occuring at a time; e.g. you can avoid swamping your db with lots of requests or an external API with too many requests.

Optionally takes maxPerPeriod and timePeriodMilliseconds (defaults to 1000) to rate limit the pulling of the promises from the generator.

Rate limiting

It is (usually) better to lower the timePeriodInMilliseconds and keep maxPerPeriod at 1, as that will spread out the requests.

Also, the time based limitation is based on initiating the requests, not on the completion of the requests. So 1, 200 would create at most 1 request every 200ms, and 5, 1000 would create 5 requests (immediately) and another batch of 5 requests are 1 second (assuming it didn't exceed n requests in flight).

Deferred vs Direct generation of promises

Since a generator only returns done when trying to read the next element if we directly return promises we have to wait out the rate limiter before calling the generator to determine if there are more promises to process. (Since the promise is scheduled immediately.)

We can move the rate limiter to after calling the generator by having the generator return a function to produce the promise (defer its generation) and only waiting if there is another promise to be processed.

Example Usage

// replace with actual request data
const requestsToMake = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ];

// replace with actual function to process the requests
async function doRequest(r) { return Date.now() + ' r: ' + r; }

// converts an iterable to a deferred stream of applications of a function
function* dgmap(iterable, f) {
  for (const n of iterable) {
    yield () => f(n); // defer running f to the callers discretion
  }
} 

// at most 4 in flight at a time, max 1 request every 200ms.
awaitn(4, dgmap(requestsToMake, doRequest), console.log, console.error, 1, 200);
0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago