UNPKG

async-throttle-cache

Version:

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

118 lines (115 loc) 3.45 kB
'use strict'; var returnSelf = function returnSelf(result) { return Promise.resolve(result); }; function asyncThrottleCache(fn, wait, _temp) { if (wait === void 0) { wait = 0; } var _ref = _temp === void 0 ? {} : _temp, _ref$key = _ref.key, key = _ref$key === void 0 ? function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return JSON.stringify(args); } : _ref$key, _ref$serialize = _ref.serialize, serialize = _ref$serialize === void 0 ? returnSelf : _ref$serialize, _ref$deserialize = _ref.deserialize, deserialize = _ref$deserialize === void 0 ? returnSelf : _ref$deserialize, _ref$debounce = _ref.debounce, debounce = _ref$debounce === void 0 ? undefined : _ref$debounce; var cache = {}; var debounceLeading = debounce == null ? void 0 : debounce.leading; return function () { var _this = this; for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } // eslint-disable-line func-names var cacheKey = key.apply(void 0, args); var cached = cache[cacheKey]; var onFinish = function onFinish(index, err, result) { var cachedF = cache[cacheKey]; if ((cachedF == null ? void 0 : cachedF.i) === index) { cachedF.f = true; if (err) { cachedF.e = err; cachedF.j.map(function (f) { return f(err); }); } else { serialize(result).then(function (r) { cachedF.r = r; cachedF.s.map(function (f, i) { return deserialize(r).then(f, cachedF.j[i]); }); }, onFinish); } if (!cachedF.t || debounce && !debounceLeading) { delete cache[cacheKey]; } } return result; }; var exec = function exec() { var cachedE = cache[cacheKey]; var i = cachedE.i = Date.now(); cachedE.f = false; return fn.apply(_this, args).then(function (result) { return onFinish(i, undefined, result); }, function (err) { onFinish(i, err); return Promise.reject(err); }); }; var timeout = function timeout() { return setTimeout(function () { var cachedT = cache[cacheKey]; if (cachedT) { if (debounce && cachedT.s.length) { exec(); } else if (cachedT.f) { delete cache[cacheKey]; } else { cachedT.t = 0; } } }, wait); }; var padding = function padding() { return new Promise(function (resolve, reject) { var cachedP = cache[cacheKey]; cachedP.s.push(resolve); cachedP.j.push(reject); }); }; if (cached) { if (debounce) { clearTimeout(cached.t); cached.t = timeout(); } else { var e = cached.e, r = cached.r, f = cached.f; if (e !== undefined) { return Promise.reject(e); } if (f) { return deserialize(r); } } return padding(); } cache[cacheKey] = { s: [], // resolve callbacks j: [], // reject callbacks t: timeout() }; return !debounce || debounceLeading ? exec() : padding(); }; } module.exports = asyncThrottleCache;