async-wrappers
Version:
A set of wrapper functions to perform debouncing, throttling, retrying etc.
122 lines (100 loc) • 2.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _pending = _interopRequireDefault(require("./pending"));
var _callReducers = require("./callReducers");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @internal
*/
/**
* @internal
*/
const wrap = (fn, before, after) => {
let wrapped = fn;
if (before && after) {
wrapped = (...args) => {
before();
const result = fn(...args);
after();
return result;
};
} else if (before) {
wrapped = (...args) => {
before();
const result = fn(...args);
return result;
};
} else if (after) {
wrapped = (...args) => {
const result = fn(...args);
after();
return result;
};
}
return wrapped;
};
/**
* @internal
*/
const getRunner = (fn, args, result) => () => {
try {
result.complete(fn(...args));
} catch (e) {
result.error(e);
}
};
/**
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
const empty = () => {};
/**
* @internal
*
* Utility function that wraps a function and will use a reducer to combine the arguments
* of multiple calls to that function. As the function is not executed until it is invoked
* a promise for the result is returned to the callers.
*
* @param fn The function to wrap.
* @param {?argumentsReducer} callReducer Used to determine the arguments when `fn` is invoked.
* This will be called every time the wrapped function is called.
* If not supplied the default implementation of only using the latest arguments will be used.
* @param onBeforeReduce If supplied this function will be called before the reducer is called.
* @param onAfterReduce If supplied this function will be called if the wrapped function is cancelled.
* @returns
*/
const callReduce = (fn, callReducer, onBeforeReduce, onAfterReduce) => {
const reducer = typeof callReducer === 'function' ? callReducer : _callReducers.latestArguments;
let result = null;
let args = [];
const reject = reason => {
if (result !== null) {
result.error(reason ? reason : new Error('reset'));
result = null;
args = [];
}
}; // capture the invocation state
const prepare = () => {
if (result === null) {
// sanity check no result pending
return empty;
}
const run = getRunner(fn, args, result);
result = null;
args = [];
return run;
};
const call = wrap((...callArgs) => {
args = reducer(args, callArgs);
if (result === null) {
result = (0, _pending.default)();
}
return result.promise;
}, onBeforeReduce, onAfterReduce);
return [call, prepare, reject];
};
var _default = callReduce;
exports.default = _default;