@ayonli/jsext
Version:
A JavaScript extension package for building strong and modern applications.
74 lines (69 loc) • 2.33 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var async = require('./async.js');
/**
* Debounces function calls for frequent access.
* @module
*/
const registry = new Map();
function debounce(handler, options, reducer = undefined) {
const delay = typeof options === "number" ? options : options.delay;
const key = typeof options === "number" ? null : options.for;
const hasKey = key !== null && key !== undefined && key !== "";
let _cache = hasKey ? registry.get(key) : undefined;
if (!_cache) {
_cache = {
for: key,
tasks: [],
data: undefined,
timer: undefined,
};
if (hasKey) {
registry.set(key, _cache);
}
}
const cache = _cache;
return async function (data) {
if (typeof reducer === "function" && cache.data !== undefined) {
cache.data = reducer(cache.data, data);
}
else {
cache.data = data;
}
cache.timer && clearTimeout(cache.timer);
cache.timer = setTimeout(() => {
// Move tasks and cached data to new variables, so during the middle
// of handler running, new calls won't affect the running process.
const _tasks = cache.tasks;
const _data = cache.data;
cache.tasks = [];
cache.data = undefined;
if (hasKey) {
registry.delete(key);
}
const resolve = (result) => {
_tasks.forEach(({ resolve }) => resolve(result));
};
const reject = (err) => {
_tasks.forEach(({ reject }) => reject(err));
};
try {
const res = handler.call(this, _data);
if (typeof (res === null || res === void 0 ? void 0 : res.then) === "function") {
Promise.resolve(res).then(resolve, reject);
}
else {
resolve(res);
}
}
catch (err) {
reject(err);
}
}, delay);
const task = async.asyncTask();
cache.tasks.push(task);
return await task;
};
}
exports.default = debounce;
//# sourceMappingURL=debounce.js.map