async-throttle-cache

Throttle asynchronous functions and return cached result for each function calls. It can be used for rate limit.

Usage no npm install needed!

<script type="module">
  import asyncThrottleCache from 'https://cdn.skypack.dev/async-throttle-cache';
</script>

README

async-throttle-cache

npm bundle size npm downloads license

github build coverage

Throttle asynchronous functions and return cached result for each function calls. It can be used for rate limit.

Installation

NPM

npm install async-throttle-cache --save
import asyncThrottleCache from 'async-throttle-cache';

Browser

Direct <script> include

<script src="https://cdn.jsdelivr.net/npm/async-throttle-cache"></script>

Usage

const throttleFn = asyncThrottleCache(fn[, wait = 0[, options = {
  key: (...args) => JSON.stringify(args),
  serialize: result => Promise.resolve(result),
  deserialize: result => Promise.resolve(result),
}]]);

Creates a throttled function that only invokes fn at most once per every wait milliseconds, and returns cached result.

You can specify how to generate cache key. Different cache key will re-invoke fn to get a new result.

serialize and deserialize is for cached result, they could be asynchronous functions.

For example, clone result for each time throttled function execution in 1000 milliseconds. It's useful when you tend to modify the result object.

const throttleFn = asyncThrottleCache(fn, 1000, {
  serialize: async result => JSON.stringify(result),
  deserialize: async result => JSON.parse(result),
});

Examples

// define a asynchronous function, return after 100ms
function fn(arg1, arg2) {
  return new Promise((resolve) => {
    setTimeout(resolve({
      arg1,
      arg2
    }), 100);
  });
}
const throttleFn200ms = asyncThrottleCache(fn, 200); // longer then function execution

async () => {
  throttleFn200ms(1, 2);       // invoke,     return { arg1: 1, arg2: 2 } at 100ms
  throttleFn200ms(1, 2);       // from cache, return { arg1: 1, arg2: 2 } at 100ms
  await throttleFn200ms(2, 2); // invoke,     return { arg1: 2, arg2: 2 } at 100ms
  await throttleFn200ms(2, 2); // from cache, return { arg1: 2, arg2: 2 } at 100ms
}();
const throttleFn50ms = asyncThrottleCache(fn, 50); // shorter then function execution

async () => {
  throttleFn50ms(1, 2);       // invoke,     return { arg1: 1, arg2: 2 } at 100ms
  throttleFn50ms(1, 2);       // from cache, return { arg1: 1, arg2: 2 } at 100ms
  await throttleFn50ms(2, 2); // invoke,     return { arg1: 2, arg2: 2 } at 100ms
  await throttleFn50ms(2, 2); // invoke,     return { arg1: 2, arg2: 2 } at 200ms
}();
const throttleFn200ms = asyncThrottleCache(fn, 200, {
  key: (arg1, arg2) => JSON.stringify(arg2) // uses arg2 as key
});

async () => {
  throttleFn200ms(1, 2);       // invoke,     return { arg1: 1, arg2: 2 } at 100ms
  throttleFn200ms(1, 2);       // from cache, return { arg1: 1, arg2: 2 } at 100ms
  await throttleFn200ms(2, 2); // from cache, return { arg1: 1, arg2: 2 } at 100ms
  await throttleFn200ms(2, 2); // from cache, return { arg1: 1, arg2: 2 } at 100ms
}();