tryloop
Version:
Simple library for retrying operations, it supports multiple backoff strategies.
82 lines (81 loc) • 2.35 kB
JavaScript
/* IMPORT */
import { isPromise, isUndefined } from '../utils.js';
/* MAIN */
class Abstract {
/* CONSTRUCTOR */
constructor(options) {
this.running = false;
this.startTime = NaN;
this.stopTime = NaN;
this.tries = 0;
this.options = Object.assign({
timeout: Infinity,
tries: Infinity
}, options); //TSC: not sure what to do about the supposed error
this.options.timeout = Math.min(2147483647, this.options.timeout);
}
/* API */
start() {
if (this.running)
return this.result;
this.running = true;
this.startTime = Date.now();
this.tries = 0;
this.result = this.loop();
return this.result;
}
stop() {
if (!this.running)
return;
this.running = false;
this.stopTime = Date.now();
}
cancel() {
return this.stop();
}
loop() {
let timeoutId;
return Promise.race([
new Promise(resolve => {
if (this.options.timeout === Infinity)
return;
timeoutId = setTimeout(() => {
this.stop();
resolve(undefined);
}, this.options.timeout);
}),
new Promise(res => {
const resolve = value => {
clearTimeout(timeoutId);
this.stop();
res(value);
};
const retry = () => this.schedule(attempt);
const attempt = () => this.try(resolve, retry);
attempt();
})
]);
}
try(resolve, retry) {
if (!this.running)
return resolve();
if ((Date.now() - this.startTime) >= this.options.timeout)
return resolve();
if (this.tries >= this.options.tries)
return resolve();
this.tries++;
const onResult = result => isUndefined(result) ? retry() : resolve(result);
const result = this.options.fn();
if (isPromise(result)) {
result.then(onResult);
}
else {
onResult(result);
}
}
schedule(_) {
throw new Error('Missing schedule function');
}
}
/* EXPORT */
export default Abstract;