UNPKG

pollsky

Version:

Chained Polling Library for Node.js: Friendly API with no external dependencies.

177 lines 6.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const errors_1 = require("./errors"); const utils_1 = require("./utils"); const debug_1 = require("./debug"); /** * ⛓ Chained Polling Library for Node.js * @public */ class Pollsky { constructor(asyncFn) { /** * The number of times the `asyncFn()` has invoked before `conditionFn()` * returns true. */ this.retries = 0; /** * */ this.failures = []; /** * Time between the end of last retry and the next one. * @default { value: 1000, unit: 'milliseconds' } */ this.pollingInterval = new utils_1.Time({ interval: 1000, unit: 'milliseconds' }); /** * Instructs Pollsky to ignore errors thrown by `asyncFn`. */ this.isIgnoreErrors = false; /** * Instructs Pollsky to return a value even if master timeout is called. */ this.isDontThrowError = false; this.asyncFn = asyncFn; } /** * Static method created only to be exported, and thus achieve "cleaner" API. */ static wait(asyncFn) { return new Pollsky(asyncFn); } /** * Starts polling. */ async until(conditionFn) { (0, debug_1.debug)(`Polling started. Parameters:`, { isIgnoreErrors: this.isIgnoreErrors, interval: this.pollingInterval, atLeastCondition: this.atLeastDuration, atMostDuration: this.atMostDuration }); const result = await this.poll(this.asyncFn, conditionFn, this.retries); if (this.atMostTimeout) { clearTimeout(this.atMostTimeout); } return result; } /** * Stops polling with failure when timeout is called. */ atMost(interval, unit) { this.atMostDuration = new utils_1.Time({ interval, unit }); this.atMostTimeout = setTimeout(() => { this.atMostTimeoutToBeCalled = true; }, this.atMostDuration.toMilliseconds()); return this; } /** * Makes polling wait at least a certain amount of time until the result is returned. */ atLeast(interval, unit) { this.atMostDuration = new utils_1.Time({ interval, unit }); this.atLeastTimeout = setTimeout(() => { this.atLeastTimeout = undefined; }, this.atMostDuration.toMilliseconds()); return this; } /** * Changes the default interval duration. */ withInterval(interval, unit) { this.pollingInterval = new utils_1.Time({ interval, unit }); return this; } /** * Causes errors thrown by `asyncFn` being ignored. */ dontThrowError() { this.isDontThrowError = true; return this; } /** * Causes errors thrown by `asyncFn` being ignored. */ ignoreErrors() { this.isIgnoreErrors = true; return this; } /** * The core method in this project, it basically contains the entire logic * required for polling. Execute the given `asyncFn` function, checks if * all of the conditions are met and handles the errors if needed be. */ async poll(asyncFn, conditionFn, retries) { try { return this.checkConditions(await this.executeAsyncFn(this.asyncFn), conditionFn); } catch (error) { if (error instanceof errors_1.PollskyError) { this.failures.push({ error: error.name, errorMsg: error.message, result: error.result, timestamp: new Date().toISOString() }); if (error instanceof errors_1.AtMostConditionError) { throw new errors_1.PollingFailedError(this.failures); } if (error instanceof errors_1.ExceptionOccurredError) { if (!this.isIgnoreErrors) { throw new errors_1.PollingFailedError(this.failures); } } await this.wait(this.pollingInterval.toMilliseconds()); return this.poll(asyncFn, conditionFn, retries + 1); } throw error; } } /** * Performs a single execution of `asyncFn` and wraps it with `try catch` * in order to throw custom error and handle it properly. */ async executeAsyncFn(asyncFn) { this.retries++; try { (0, debug_1.debug)(`Executing asyncFn()... Retry: ${this.retries}`); return await asyncFn(); } catch (error) { throw new errors_1.ExceptionOccurredError(error.message, { timestamp: (0, utils_1.getTimestamp)() }); } } /** * Checks if all conditions are met and if not, throws a custom error. */ checkConditions(result, conditionFn) { if (this.atMostTimeoutToBeCalled) { if (this.isDontThrowError) { (0, debug_1.debug)('Master timeout called but the flag returnValueIfFailed is set'); (0, debug_1.debug)('Returning the last result.'); return result; } throw new errors_1.AtMostConditionError({ timestamp: (0, utils_1.getTimestamp)(), result: result }); } if (conditionFn(result) === false) { throw new errors_1.ConditionFunctionError({ timestamp: (0, utils_1.getTimestamp)(), result: result }); } if (this.atLeastTimeout) { throw new errors_1.AtLeastConditionError({ timestamp: (0, utils_1.getTimestamp)(), result: result }); } (0, debug_1.debug)('Polling finished with success - conditionFn() returned `true`.'); (0, debug_1.debug)('Returning the last result.'); return result; } /** * Waits certain amout of time. */ wait(duration) { return new Promise(resolve => setTimeout(resolve, duration)); } } exports.default = Pollsky; //# sourceMappingURL=pollsky.js.map