Skip to content

Instantly share code, notes, and snippets.

@vitaly-t
Last active May 20, 2025 15:20
Show Gist options
  • Select an option

  • Save vitaly-t/6e3d285854d882b1618c7e435df164c4 to your computer and use it in GitHub Desktop.

Select an option

Save vitaly-t/6e3d285854d882b1618c7e435df164c4 to your computer and use it in GitHub Desktop.

Revisions

  1. vitaly-t revised this gist Apr 13, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -27,7 +27,7 @@ export type RetryStatus<D = unknown> = {
    /**
    * Retry-status callback type.
    */
    export type RetryCB<T, D> = (s: RetryStatus<D>) => T;
    export type RetryCB<T, D = unknown> = (s: RetryStatus<D>) => T;

    /**
    * Type for options passed into retryAsync function.
  2. vitaly-t revised this gist Apr 6, 2025. 1 changed file with 27 additions and 13 deletions.
    40 changes: 27 additions & 13 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,55 +1,69 @@
    /**
    * Retry-status object type, for use with RetryCB.
    */
    export type RetryStatus = {
    export type RetryStatus<D = unknown> = {
    /**
    * Retry index, starting from 0.
    */
    index: number,
    readonly index: number,

    /**
    * Retry overall duration, in milliseconds.
    */
    duration: number,
    readonly duration: number,

    /**
    * Last error, if available;
    * it is undefined only when "retryAsync" calls "func" with index = 0.
    */
    error?: any
    readonly error?: Error,

    /**
    * Extra data for status handlers, if specified.
    */
    readonly data?: D
    };

    /**
    * Retry-status callback type.
    */
    export type RetryCB<T> = (s: RetryStatus) => T;
    export type RetryCB<T, D> = (s: RetryStatus<D>) => T;

    /**
    * Type for options passed into retryAsync function.
    */
    export type RetryOptions = {
    export type RetryOptions<D = unknown> = {
    /**
    * Maximum number of retries (infinite by default),
    * or a callback to indicate the need for another retry.
    */
    retry?: number | RetryCB<boolean>,
    readonly retry?: number | RetryCB<boolean, D>,

    /**
    * Retry delays, in milliseconds (no delay by default),
    * or a callback that returns the delays.
    */
    delay?: number | RetryCB<number>,
    readonly delay?: number | RetryCB<number, D>,

    /**
    * Error notifications.
    */
    error?: RetryCB<void>
    readonly error?: RetryCB<void, D>,

    /**
    * Extra data for status handlers.
    */
    readonly data?: D
    };

    /**
    * Retries async operation returned from "func" callback, according to "options".
    */
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions): Promise<T> {
    export function retryAsync<T, D>(func: RetryCB<Promise<T>, D>, options?: RetryOptions<D>): Promise<T> {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e});
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error, data} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e, data});
    const c = (): Promise<T> => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(s());
    @@ -61,4 +75,4 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(c) : c();
    });
    return c();
    }
    }
  3. vitaly-t revised this gist Sep 7, 2024. 1 changed file with 9 additions and 8 deletions.
    17 changes: 9 additions & 8 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -3,15 +3,15 @@
    */
    export type RetryStatus = {
    /**
    * retry index, starting from 0
    * Retry index, starting from 0.
    */
    index: number,
    /**
    * retry overall duration, in ms
    * Retry overall duration, in milliseconds.
    */
    duration: number,
    /**
    * last error, if available;
    * Last error, if available;
    * it is undefined only when "retryAsync" calls "func" with index = 0.
    */
    error?: any
    @@ -27,16 +27,17 @@ export type RetryCB<T> = (s: RetryStatus) => T;
    */
    export type RetryOptions = {
    /**
    * maximum number of retries (infinite by default),
    * or a callback to indicate the need for another retry
    * Maximum number of retries (infinite by default),
    * or a callback to indicate the need for another retry.
    */
    retry?: number | RetryCB<boolean>,
    /**
    * retry delays, in ms, or a callback that returns them
    * Retry delays, in milliseconds (no delay by default),
    * or a callback that returns the delays.
    */
    delay?: number | RetryCB<number>,
    /**
    * error notifications
    * Error notifications.
    */
    error?: RetryCB<void>
    };
    @@ -60,4 +61,4 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(c) : c();
    });
    return c();
    }
    }
  4. vitaly-t revised this gist Aug 31, 2024. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -42,23 +42,22 @@ export type RetryOptions = {
    };

    /**
    * Retries async operation returned from "func" callback, according to options.
    * Retries async operation returned from "func" callback, according to "options".
    */
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions): Promise<T> {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e});
    const c: () => Promise<T> = () => func(s()).catch(err => {
    const c = (): Promise<T> => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(s());
    const r = typeof retry === 'function' ? (retry(s()) ? 1 : 0) : retry--;
    if (r <= 0) {
    if ((typeof retry === 'function' ? (retry(s()) ? 1 : 0) : retry--) <= 0) {
    return Promise.reject(e);
    }
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(c) : c();
    });
    return c();
    }
    }
  5. vitaly-t revised this gist Aug 30, 2024. 1 changed file with 5 additions and 3 deletions.
    8 changes: 5 additions & 3 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -53,10 +53,12 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    e = err;
    typeof error === 'function' && error(s());
    const r = typeof retry === 'function' ? (retry(s()) ? 1 : 0) : retry--;
    if (r <= 0) {
    return Promise.reject(e);
    }
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
    const t = () => r > 0 ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(c) : c();
    });
    return c();
    }
    }
  6. vitaly-t revised this gist Aug 18, 2024. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -48,14 +48,14 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e}); // status creator
    const s = () => ({index, duration: Date.now() - start, error: e});
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(s()); // error notification
    const r = typeof retry === 'function' ? retry(s()) : retry--; // retry flag/value
    const d = typeof delay === 'function' ? delay(s()) : delay; // delay value
    typeof error === 'function' && error(s());
    const r = typeof retry === 'function' ? (retry(s()) ? 1 : 0) : retry--;
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
    const t = () => r ? c() : Promise.reject(e); // retry vs reject test
    const t = () => r > 0 ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
    });
    return c();
  7. vitaly-t revised this gist Aug 18, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -44,7 +44,7 @@ export type RetryOptions = {
    /**
    * Retries async operation returned from "func" callback, according to options.
    */
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions): Promise<T> {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
  8. vitaly-t revised this gist Aug 14, 2024. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,6 @@ export type RetryStatus = {
    duration: number,
    /**
    * last error, if available;
    *
    * it is undefined only when "retryAsync" calls "func" with index = 0.
    */
    error?: any
    @@ -53,8 +52,8 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(s()); // error notification
    const r = typeof retry === 'function' ? retry(s()) : retry--; // get retry flag
    const d = typeof delay === 'function' ? delay(s()) : delay; // get delay value
    const r = typeof retry === 'function' ? retry(s()) : retry--; // retry flag/value
    const d = typeof delay === 'function' ? delay(s()) : delay; // delay value
    index++;
    const t = () => r ? c() : Promise.reject(e); // retry vs reject test
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
  9. vitaly-t revised this gist Aug 14, 2024. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,9 @@ export type RetryStatus = {
    */
    duration: number,
    /**
    * last error, if available
    * last error, if available;
    *
    * it is undefined only when "retryAsync" calls "func" with index = 0.
    */
    error?: any
    };
    @@ -42,8 +44,6 @@ export type RetryOptions = {

    /**
    * Retries async operation returned from "func" callback, according to options.
    *
    * Note that "func()" will receive "error" = undefined when "index" = 0.
    */
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    const start = Date.now();
  10. vitaly-t revised this gist Aug 14, 2024. 1 changed file with 43 additions and 21 deletions.
    64 changes: 43 additions & 21 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,41 +1,63 @@
    // retry-status object:
    // - "index": retry index, starting from 0
    // - "duration": retry overall duration, in ms
    // - "error": last error, if available
    export type RetryStatus = { index: number, duration: number, error?: any };
    /**
    * Retry-status object type, for use with RetryCB.
    */
    export type RetryStatus = {
    /**
    * retry index, starting from 0
    */
    index: number,
    /**
    * retry overall duration, in ms
    */
    duration: number,
    /**
    * last error, if available
    */
    error?: any
    };

    // retry-status callback;
    /**
    * Retry-status callback type.
    */
    export type RetryCB<T> = (s: RetryStatus) => T;

    /**
    * Type for options passed into retryAsync function.
    */
    export type RetryOptions = {
    // maximum number of retries (infinite by default),
    // or a callback to indicate the need for another retry;
    /**
    * maximum number of retries (infinite by default),
    * or a callback to indicate the need for another retry
    */
    retry?: number | RetryCB<boolean>,

    // retry delays, in ms, or a callback that returns them;
    /**
    * retry delays, in ms, or a callback that returns them
    */
    delay?: number | RetryCB<number>,

    // error notifications;
    /**
    * error notifications
    */
    error?: RetryCB<void>
    };

    // retries async operation returned from "func" callback, according to options;
    // note that "func()" will receive "error" = undefined when "index" = 0.
    /**
    * Retries async operation returned from "func" callback, according to options.
    *
    * Note that "func()" will receive "error" = undefined when "index" = 0.
    */
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e});
    const s = () => ({index, duration: Date.now() - start, error: e}); // status creator
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(s());
    const r = typeof retry === 'function' ? retry(s()) : retry--;
    const d = typeof delay === 'function' ? delay(s()) : delay;
    typeof error === 'function' && error(s()); // error notification
    const r = typeof retry === 'function' ? retry(s()) : retry--; // get retry flag
    const d = typeof delay === 'function' ? delay(s()) : delay; // get delay value
    index++;
    const t = () => r ? c() : Promise.reject(e);
    const t = () => r ? c() : Promise.reject(e); // retry vs reject test
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
    });
    return c();
    }

    // Tested against TypeScript 5.x, in strict mode.
  11. vitaly-t revised this gist Aug 14, 2024. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -32,8 +32,8 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    const r = typeof retry === 'function' ? retry(s()) : retry--;
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
    const p = () => r ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(p) : p();
    const t = () => r ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(t) : t();
    });
    return c();
    }
  12. vitaly-t revised this gist Aug 11, 2024. 1 changed file with 5 additions and 6 deletions.
    11 changes: 5 additions & 6 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,23 +1,22 @@
    // retry status object:
    // retry-status object:
    // - "index": retry index, starting from 0
    // - "duration": retry overall duration, in ms
    // - "error": last error, if available
    export type RetryStatus = { index: number, duration: number, error?: any };

    // retry status for callbacks;
    // retry-status callback;
    export type RetryCB<T> = (s: RetryStatus) => T;

    export type RetryOptions = {
    // maximum number of retries (infinite by default),
    // or a callback to indicate the need for another retry;
    retry?: number | RetryCB<boolean>,

    // retry delays, in ms, or a callback that returns them;
    delay?: number | RetryCB<number>,

    // error notifications;
    // it receives: the error + errors count (>=1).
    error?: (e: any, c: number) => void
    error?: RetryCB<void>
    };

    // retries async operation returned from "func" callback, according to options;
    @@ -29,7 +28,7 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    const s = () => ({index, duration: Date.now() - start, error: e});
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(e, index + 1);
    typeof error === 'function' && error(s());
    const r = typeof retry === 'function' ? retry(s()) : retry--;
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
  13. vitaly-t revised this gist Aug 11, 2024. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -38,3 +38,5 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    });
    return c();
    }

    // Tested against TypeScript 5.x, in strict mode.
  14. vitaly-t revised this gist Aug 11, 2024. 1 changed file with 3 additions and 9 deletions.
    12 changes: 3 additions & 9 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    // retry status object:
    // - "index": retry index, starting from 0
    // - "duration": retry overall duration, in ms
    // - "error": last retry error, if available
    // - "error": last error, if available
    export type RetryStatus = { index: number, duration: number, error?: any };

    // retry status callback;
    // retry status for callbacks;
    export type RetryCB<T> = (s: RetryStatus) => T;

    export type RetryOptions = {
    @@ -26,7 +26,7 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    const s = () => ({index, duration: Date.now() - start, error: e}); // status
    const s = () => ({index, duration: Date.now() - start, error: e});
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(e, index + 1);
    @@ -38,9 +38,3 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)
    });
    return c();
    }

    /**
    TIPS:
    - If you need a timeout, use callback for "retry", checking for "duration" in the status;
    though it is a between-retry timeout, i.e. we do not cancel promises here ;)
    */
  15. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -41,5 +41,6 @@ export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions)

    /**
    TIPS:
    - If you need a timeout, use callback for "retry", checking for "duration" in the status.
    - If you need a timeout, use callback for "retry", checking for "duration" in the status;
    though it is a between-retry timeout, i.e. we do not cancel promises here ;)
    */
  16. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 9 additions and 4 deletions.
    13 changes: 9 additions & 4 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -2,12 +2,12 @@
    // - "index": retry index, starting from 0
    // - "duration": retry overall duration, in ms
    // - "error": last retry error, if available
    type RetryStatus = { index: number, duration: number, error?: any };
    export type RetryStatus = { index: number, duration: number, error?: any };

    // retry status callback;
    type RetryCB<T> = (s: RetryStatus) => T;
    export type RetryCB<T> = (s: RetryStatus) => T;

    type RetryOptions = {
    export type RetryOptions = {
    // maximum number of retries (infinite by default),
    // or a callback to indicate the need for another retry;
    retry?: number | RetryCB<boolean>,
    @@ -22,7 +22,7 @@ type RetryOptions = {

    // retries async operation returned from "func" callback, according to options;
    // note that "func()" will receive "error" = undefined when "index" = 0.
    function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    export function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    @@ -38,3 +38,8 @@ function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    });
    return c();
    }

    /**
    TIPS:
    - If you need a timeout, use callback for "retry", checking for "duration" in the status.
    */
  17. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@
    type RetryStatus = { index: number, duration: number, error?: any };

    // retry status callback;
    type RetryCB<T> = (cb: RetryStatus) => T;
    type RetryCB<T> = (s: RetryStatus) => T;

    type RetryOptions = {
    // maximum number of retries (infinite by default),
  18. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 17 additions and 10 deletions.
    27 changes: 17 additions & 10 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,11 @@
    // retry status callback, which receives 2 parameters:
    // retry index (>=0), plus the last error (if available)
    type RetryCB<T> = (i: number, e: any) => T;
    // retry status object:
    // - "index": retry index, starting from 0
    // - "duration": retry overall duration, in ms
    // - "error": last retry error, if available
    type RetryStatus = { index: number, duration: number, error?: any };

    // retry status callback;
    type RetryCB<T> = (cb: RetryStatus) => T;

    type RetryOptions = {
    // maximum number of retries (infinite by default),
    @@ -16,16 +21,18 @@ type RetryOptions = {
    };

    // retries async operation returned from "func" callback, according to options;
    // note that "func(i, e)" will receive "e" = undefined when "i" = 0.
    // note that "func()" will receive "error" = undefined when "index" = 0.
    function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    const start = Date.now();
    let index = 0, e: any;
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    let i = 0, e: any;
    const c: () => Promise<T> = () => func(i, e).catch(err => {
    const s = () => ({index, duration: Date.now() - start, error: e}); // status
    const c: () => Promise<T> = () => func(s()).catch(err => {
    e = err;
    typeof error === 'function' && error(e, i + 1);
    const r = typeof retry === 'function' ? retry(i, e) : retry--;
    const d = typeof delay === 'function' ? delay(i, e) : delay;
    i++;
    typeof error === 'function' && error(e, index + 1);
    const r = typeof retry === 'function' ? retry(s()) : retry--;
    const d = typeof delay === 'function' ? delay(s()) : delay;
    index++;
    const p = () => r ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(p) : p();
    });
  19. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@ type RetryOptions = {
    // retries async operation returned from "func" callback, according to options;
    // note that "func(i, e)" will receive "e" = undefined when "i" = 0.
    function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options ?? {};
    let i = 0, e: any;
    const c: () => Promise<T> = () => func(i, e).catch(err => {
    e = err;
  20. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 23 additions and 14 deletions.
    37 changes: 23 additions & 14 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,24 +1,33 @@
    type AsyncRetryOptions = {
    // maximum number of retries (infinite by default);
    retry?: number,
    // retry status callback, which receives 2 parameters:
    // retry index (>=0), plus the last error (if available)
    type RetryCB<T> = (i: number, e: any) => T;

    type RetryOptions = {
    // maximum number of retries (infinite by default),
    // or a callback to indicate the need for another retry;
    retry?: number | RetryCB<boolean>,

    // retry delays, in ms, or a callback that returns them;
    // the callback receives: retry index (from 0) + the error.
    delay?: number | ((i: number, e: any) => number),
    delay?: number | RetryCB<number>,

    // error notifications;
    error?: (e: any) => void
    // it receives: the error + errors count (>=1).
    error?: (e: any, c: number) => void
    };

    // retries async operation returned from "func" callback, according to options
    function retryAsync<T>(func: () => Promise<T>, options?: AsyncRetryOptions) {
    // retries async operation returned from "func" callback, according to options;
    // note that "func(i, e)" will receive "e" = undefined when "i" = 0.
    function retryAsync<T>(func: RetryCB<Promise<T>>, options?: RetryOptions) {
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    let i = 0; // retry index
    const c: () => Promise<T> = () => func().catch(e => {
    const r = () => retry-- ? c() : Promise.reject(e);
    typeof error === 'function' && error(e);
    const d = typeof delay === 'function' ? delay(i++, e) : delay;
    return d >= 0 ? (new Promise(r => setTimeout(r, d))).then(r) : r();
    let i = 0, e: any;
    const c: () => Promise<T> = () => func(i, e).catch(err => {
    e = err;
    typeof error === 'function' && error(e, i + 1);
    const r = typeof retry === 'function' ? retry(i, e) : retry--;
    const d = typeof delay === 'function' ? delay(i, e) : delay;
    i++;
    const p = () => r ? c() : Promise.reject(e);
    return d >= 0 ? (new Promise(a => setTimeout(a, d))).then(p) : p();
    });
    return c();
    }
  21. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,21 +1,21 @@
    type AsyncRetryOptions = {
    // maximum number of retries (infinite by default);
    retries?: number,
    retry?: number,

    // retry delays, in ms, or a callback that returns one;
    // retry delays, in ms, or a callback that returns them;
    // the callback receives: retry index (from 0) + the error.
    delay?: number | ((i: number, e: any) => number),

    // errors notification;
    // error notifications;
    error?: (e: any) => void
    };

    // retries async operation returned from "func" callback, according to options
    function retryAsync<T>(func: () => Promise<T>, options?: AsyncRetryOptions) {
    let {retries = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    let {retry = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    let i = 0; // retry index
    const c: () => Promise<T> = () => func().catch(e => {
    const r = () => retries-- ? c() : Promise.reject(e);
    const r = () => retry-- ? c() : Promise.reject(e);
    typeof error === 'function' && error(e);
    const d = typeof delay === 'function' ? delay(i++, e) : delay;
    return d >= 0 ? (new Promise(r => setTimeout(r, d))).then(r) : r();
  22. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ type AsyncRetryOptions = {
    // the callback receives: retry index (from 0) + the error.
    delay?: number | ((i: number, e: any) => number),

    // errors notification:
    // errors notification;
    error?: (e: any) => void
    };

  23. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ type AsyncRetryOptions = {
    // retries async operation returned from "func" callback, according to options
    function retryAsync<T>(func: () => Promise<T>, options?: AsyncRetryOptions) {
    let {retries = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    let i = 0;// retry index
    let i = 0; // retry index
    const c: () => Promise<T> = () => func().catch(e => {
    const r = () => retries-- ? c() : Promise.reject(e);
    typeof error === 'function' && error(e);
  24. vitaly-t revised this gist Aug 10, 2024. 1 changed file with 16 additions and 8 deletions.
    24 changes: 16 additions & 8 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,24 @@
    type AsyncRetryOptions = {
    retries?: number, // maximum retries (infinite by default)
    delay?: number, // delay between retries, in ms
    error?: (e: any) => void // errors notification
    // maximum number of retries (infinite by default);
    retries?: number,

    // retry delays, in ms, or a callback that returns one;
    // the callback receives: retry index (from 0) + the error.
    delay?: number | ((i: number, e: any) => number),

    // errors notification:
    error?: (e: any) => void
    };

    // retries async operation returned from "func" callback, according to options
    function retryAsync<T>(func: () => Promise<T>, options?: AsyncRetryOptions) {
    let {retries = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    const call: () => Promise<T> = () => func().catch(e => {
    const r = () => retries-- ? call() : Promise.reject(e);
    let i = 0;// retry index
    const c: () => Promise<T> = () => func().catch(e => {
    const r = () => retries-- ? c() : Promise.reject(e);
    typeof error === 'function' && error(e);
    return delay >= 0 ? (new Promise(r => setTimeout(r, delay))).then(r) : r();
    const d = typeof delay === 'function' ? delay(i++, e) : delay;
    return d >= 0 ? (new Promise(r => setTimeout(r, d))).then(r) : r();
    });
    return call();
    return c();
    }

  25. vitaly-t created this gist Aug 9, 2024.
    16 changes: 16 additions & 0 deletions retry-async.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    type AsyncRetryOptions = {
    retries?: number, // maximum retries (infinite by default)
    delay?: number, // delay between retries, in ms
    error?: (e: any) => void // errors notification
    };

    function retryAsync<T>(func: () => Promise<T>, options?: AsyncRetryOptions) {
    let {retries = Number.POSITIVE_INFINITY, delay = -1, error} = options || {};
    const call: () => Promise<T> = () => func().catch(e => {
    const r = () => retries-- ? call() : Promise.reject(e);
    typeof error === 'function' && error(e);
    return delay >= 0 ? (new Promise(r => setTimeout(r, delay))).then(r) : r();
    });
    return call();
    }