@hirosystems/api-toolkit
Version:
API development toolkit
121 lines • 3.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.timeout = timeout;
exports.time = time;
exports.resolveOrTimeout = resolveOrTimeout;
exports.stopwatch = stopwatch;
exports.waiter = waiter;
const promises_1 = require("node:timers/promises");
/**
* Wait a set amount of milliseconds or until the timer is aborted.
* @param ms - Number of milliseconds to wait
* @param abort - Abort controller
* @returns Promise
*/
function timeout(ms, abort) {
const signal = abort && (abort instanceof AbortSignal ? abort : abort.signal);
return (0, promises_1.setTimeout)(ms, undefined, { signal });
}
/**
* Time the execution of an async function.
* @param fn - Async function
* @param onFinish - Callback with elapsed milliseconds
* @returns Promise
*/
async function time(fn, onFinish) {
const watch = stopwatch();
try {
return await fn();
}
finally {
onFinish(watch.getElapsed());
}
}
/**
* Set an execution time limit for a promise.
* @param promise - The promise being capped to `timeoutMs` max execution time
* @param timeoutMs - Timeout limit in milliseconds
* @param wait - If we should wait another `timeoutMs` period for `promise` to resolve
* @param waitHandler - If `wait` is `true`, this closure will be executed before waiting another
* `timeoutMs` cycle
* @returns `true` if `promise` ended gracefully, `false` if timeout was reached
*/
async function resolveOrTimeout(promise, timeoutMs, wait = false, waitHandler) {
let timer;
const result = await Promise.race([
new Promise((resolve, reject) => {
promise
.then(() => resolve(true))
.catch(error => reject(error))
.finally(() => clearTimeout(timer));
}),
new Promise((resolve, _) => {
timer = setInterval(() => {
if (!wait) {
clearTimeout(timer);
resolve(false);
return;
}
if (waitHandler) {
waitHandler();
}
}, timeoutMs);
}),
]);
return result;
}
/**
* Start a `Stopwatch` that measures elapsed time based on `process.hrtime`.
* @returns Stopwatch
*/
function stopwatch() {
let start = process.hrtime.bigint();
const result = {
getElapsedSeconds: () => {
const elapsedMs = result.getElapsed();
return elapsedMs / 1000;
},
getElapsed: () => {
const end = process.hrtime.bigint();
return Number((end - start) / 1000000n);
},
getElapsedAndRestart: () => {
const end = process.hrtime.bigint();
const result = Number((end - start) / 1000000n);
start = process.hrtime.bigint();
return result;
},
restart: () => {
start = process.hrtime.bigint();
},
};
return result;
}
/**
* Creates a `Waiter` promise that can be resolved or rejected at a later time.
* @returns Waiter
*/
function waiter() {
let resolveFn;
let rejectFn;
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
const completer = {
finish: (result) => completer.resolve(result),
resolve: (result) => {
void Object.assign(promise, { isFinished: true, isResolved: true });
resolveFn(result);
},
reject: (error) => {
void Object.assign(promise, { isFinished: true, isRejected: true });
rejectFn(error);
},
isFinished: false,
isResolved: false,
isRejected: false,
};
return Object.assign(promise, completer);
}
//# sourceMappingURL=time.js.map