Interface Strategy

A Strategy is any iterable iterator which yields numbers. You can implement it using the IterableIterator interface, i.e. implements Strategy, or you can write a generator function which produces Generator<number>.

You can define your own generator functions or iterable iterators and pass them as the strategy for the delay, or you can implement a class which implements this interface. If you are able to target ES2025 (including by using a polyfill), you can also provide subclasses of Iterator.

function* randomInRange(min: number, max: number): Strategy<number> {
while (true) {
let scaled = Math.random() * (max - min + 1);
let scaledInt = Math.floor(scaled);
let startingAtMin = scaledInt + min;
yield startingAtMin
}
}

//
class RandomInteger implements Strategy {
#nextValue: number;

constructor(initial: number) {
this.#nextValue = initial;
}

next(): IteratorResult<number, void> {
this.#nextValue = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
return { done: false, value: this.#nextValue };
}

return(value: number): IteratorResult<number, void> {
return { done: false, value };
}

throw(_error: unknown): IteratorResult<number, void> {
return { done: true, value: undefined };
}

[Symbol.iterator](): Generator<number, any, unknown> {
return this;
}
}

class Range extends Iterator {
readonly #start: number;
readonly #end: number;
readonly #step: number;

constructor(start: number, end: number, step = 1) {
this.#start = start;
this.#end = end;
this.#step = step;
}

*[Symbol.iterator]() {
for (let value = this.#start; value <= this.#end; value += this.#step) {
yield value;
}
}
}

Then you can use any of these as a retry strategy (note that these examples assume you have access to the ES2025 iterator helper methods):

import * as Task from 'true-myth/task';
import { someRetryableTask } from 'somewhere/in/your-app';

let usingRandomInRange = Task.withRetries(
someRetryableTask,
randomInRange(1, 100).take(10)
);

let usingRandomInteger = Task.withRetries(
someRetryableTask,
new RandomInteger().take(10)
);

let usingRangeIterator = Task.withRetries(
someRetryableTask,
new Range(1, 100, 5).take(10)
);
interface Strategy {
    "[iterator]"(): Generator<number>;
    next(...__namedParameters: [] | [any]): IteratorResult<number, any>;
    return(value: any): IteratorResult<number, any>;
    throw(e: any): IteratorResult<number, any>;
}

Hierarchy

  • Generator<number>
    • Strategy

Methods

  • Returns Generator<number>

  • Parameters

    • ...__namedParameters: [] | [any]

    Returns IteratorResult<number, any>

  • Parameters

    • value: any

    Returns IteratorResult<number, any>

  • Parameters

    • e: any

    Returns IteratorResult<number, any>