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))
})