diff --git a/docs/modules/Async.md b/docs/modules/Async.md index 54a6450..2bcdba2 100644 --- a/docs/modules/Async.md +++ b/docs/modules/Async.md @@ -60,4 +60,29 @@ const res = await Promise.all([ seq ➔ [200, 100, 150] res ➔ [200, 100, 150] +``` + +### retry + +```ts +RetryOption = { + /** + * The time to wait between retries, in milliseconds. The default is 0. + */ + interval?: number; + /** + * The number of attempts to make before giving up. The default is 3. + */ + times?: number; +} + +(fn: ((times: number) => Promise) | (() => A), times?: number): Promise; +(fn: ((times: number) => Promise) | (() => A), options: RetryOption): Promise; +``` + +Attempts to get a successful response from task no more than times times before returning an error. + +```ts +await retry(() => new Promise(r => r(1)), 3) ➔ 1 +await retry(() => 2), { times: 3, interval: 300 }) ➔ 2 ``` \ No newline at end of file diff --git a/docs/modules/Math.md b/docs/modules/Math.md index d642dfe..1be0906 100644 --- a/docs/modules/Math.md +++ b/docs/modules/Math.md @@ -93,7 +93,7 @@ between(2, 1, 2, { from: true, to: true }) ➔ false (min: number, max: number) => number ``` -Returns a random integer from min to max (includes min and max). +Returns a random integer from min to max (includes min and excludes max). ```ts randrange(0, 100) ➔ 50 // a random number between 0 and 100 diff --git a/src/Async.ts b/src/Async.ts index d417259..f5c4f92 100644 --- a/src/Async.ts +++ b/src/Async.ts @@ -89,6 +89,7 @@ export type RetryOption = { */ times?: number } +type Fn = ((times: number) => Promise) | (() => A) /** * Attempts to get a successful response from task no more than times times before returning an error. * @@ -102,11 +103,12 @@ export type RetryOption = { * assert.deepStrictEqual(res, 2) * ``` */ -export async function retry(fn: (() => PromiseLike) | (() => A), times?: number): Promise -export async function retry(fn: (() => Promise) | (() => A), options: RetryOption): Promise -export async function retry(fn: (() => Promise) | (() => A), options: number | RetryOption = 1): Promise { - let interval = 0 - let times = 1 +export async function retry(fn: Fn, times?: number): Promise +export async function retry(fn: Fn, options: RetryOption): Promise +export async function retry(fn: Fn, options: number | RetryOption = 1): Promise { + let interval: number + let times: number + let retry = 1 if(typeof options === 'number') { times = options @@ -116,12 +118,13 @@ export async function retry(fn: (() => Promise) | (() => A), options: numb } return new Promise((resolve, reject) => { - const attempt = () => { + const attempt = async () => { try { - resolve(fn()) + const res = await fn(retry) + resolve(res) } catch(error) { - if (times > 0) { - times-- + if (retry < times) { + retry++ interval ? setTimeout(attempt, interval) : attempt() } else { reject(error) diff --git a/test/Async.spec.ts b/test/Async.spec.ts index b4bf0f0..e5c4cb0 100644 --- a/test/Async.spec.ts +++ b/test/Async.spec.ts @@ -62,6 +62,10 @@ test('retry', async () => { retry(() => 1).then(r => expect(r).toBe(1)) retry(() => 2, 3).then(r => expect(r).toBe(2)) retry(() => new Promise(r => r(3))).then(r => expect(r).toBe(3)) - retry(() => new Promise(r => r(4)), { times: 3, interval: 200 }).then(r => expect(r).toBe(4)) - retry(() => new Promise((_, r) => r(-1)), 3).catch(e => expect(e).toBe(-1)) + retry(() => new Promise(r => r(4)), { interval: 200 }).then(r => expect(r).toBe(4)) + retry((retry) => new Promise((_, e) => e(retry)), { times: 2 }).catch(e => expect(e).toBe(2)) + retry((retry) => new Promise((then, error) => { + if (retry === 3) return then(retry) + error(-1) + }), { times: 3, interval: 200 }).catch(e => expect(e).toBe(3)) })