+38
| import {OperationOptions} from 'retry'; | ||
| export interface FailedAttemptError extends Error { | ||
| readonly attemptNumber: number; | ||
| readonly retriesLeft: number; | ||
| } | ||
| export interface Options extends OperationOptions { | ||
| /** | ||
| * Callback invoked on each retry. Receives the error thrown by `input` as the first argument with properties `attemptNumber` and `retriesLeft` which indicate the current attempt number and the number of attempts left, respectively. | ||
| */ | ||
| readonly onFailedAttempt?: (error: FailedAttemptError) => void; | ||
| } | ||
| /** | ||
| * Returns a `Promise` that is fulfilled when calling `input` returns a fulfilled promise. If calling `input` returns a rejected promise, `input` is called again until the max retries are reached, it then rejects with the last rejection reason. | ||
| * | ||
| * It doesn't retry on `TypeError` as that's a user error. | ||
| * | ||
| * @param input - Receives the number of attempts as the first argument and is expected to return a `Promise` or any value. | ||
| * @param options - Options are passed to the [`retry`](https://github.com/tim-kos/node-retry#retryoperationoptions) module. | ||
| */ | ||
| export default function pRetry<T>( | ||
| input: (attemptCount: number) => PromiseLike<T> | T, | ||
| options?: Options | ||
| ): Promise<T>; | ||
| export class AbortError extends Error { | ||
| readonly name: 'AbortError'; | ||
| readonly originalError: Error; | ||
| /** | ||
| * Abort retrying and reject the promise. | ||
| * | ||
| * @param message - Error message or custom error. | ||
| */ | ||
| constructor(message: string | Error); | ||
| } |
+25
-16
@@ -21,3 +21,3 @@ 'use strict'; | ||
| function decorateErrorWithCounts(error, attemptNumber, options) { | ||
| const decorateErrorWithCounts = (error, attemptNumber, options) => { | ||
| // Minus 1 from attemptNumber because the first attempt does not count as a retry | ||
@@ -28,17 +28,23 @@ const retriesLeft = options.retries - (attemptNumber - 1); | ||
| error.retriesLeft = retriesLeft; | ||
| return error; | ||
| } | ||
| }; | ||
| module.exports = (input, options) => new Promise((resolve, reject) => { | ||
| options = Object.assign({ | ||
| const pRetry = (input, options) => new Promise((resolve, reject) => { | ||
| options = { | ||
| onFailedAttempt: () => {}, | ||
| retries: 10 | ||
| }, options); | ||
| retries: 10, | ||
| ...options | ||
| }; | ||
| const operation = retry.operation(options); | ||
| operation.attempt(attemptNumber => Promise.resolve(attemptNumber) | ||
| .then(input) | ||
| .then(resolve, error => { | ||
| operation.attempt(async attemptNumber => { | ||
| try { | ||
| resolve(await input(attemptNumber)); | ||
| } catch (error) { | ||
| if (!(error instanceof Error)) { | ||
| reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`)); | ||
| return; | ||
| } | ||
| if (error instanceof AbortError) { | ||
@@ -50,14 +56,17 @@ operation.stop(); | ||
| reject(error); | ||
| } else if (operation.retry(error)) { | ||
| decorateErrorWithCounts(error, attemptNumber, options); | ||
| options.onFailedAttempt(error); | ||
| } else { | ||
| decorateErrorWithCounts(error, attemptNumber, options); | ||
| options.onFailedAttempt(error); | ||
| reject(operation.mainError()); | ||
| if (!operation.retry(error)) { | ||
| reject(operation.mainError()); | ||
| } | ||
| } | ||
| }) | ||
| ); | ||
| } | ||
| }); | ||
| }); | ||
| module.exports = pRetry; | ||
| module.exports.default = pRetry; | ||
| module.exports.AbortError = AbortError; |
+8
-5
| { | ||
| "name": "p-retry", | ||
| "version": "3.0.1", | ||
| "version": "4.0.0", | ||
| "description": "Retry a promise-returning or async function", | ||
@@ -13,9 +13,10 @@ "license": "MIT", | ||
| "engines": { | ||
| "node": ">=6" | ||
| "node": ">=8" | ||
| }, | ||
| "scripts": { | ||
| "test": "xo && ava" | ||
| "test": "xo && ava && tsd-check" | ||
| }, | ||
| "files": [ | ||
| "index.js" | ||
| "index.js", | ||
| "index.d.ts" | ||
| ], | ||
@@ -42,9 +43,11 @@ "keywords": [ | ||
| "dependencies": { | ||
| "@types/retry": "^0.12.0", | ||
| "retry": "^0.12.0" | ||
| }, | ||
| "devDependencies": { | ||
| "ava": "^1.1.0", | ||
| "ava": "^1.3.1", | ||
| "delay": "^4.1.0", | ||
| "tsd-check": "^0.3.0", | ||
| "xo": "^0.24.0" | ||
| } | ||
| } |
8018
26.07%5
25%90
80%2
100%4
33.33%+ Added
+ Added