Skip to content

Commit

Permalink
fix: Allow retrying with non-Promise thenables
Browse files Browse the repository at this point in the history
  • Loading branch information
nzakas committed May 3, 2024
1 parent 6db941c commit 70f33c0
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/retrier.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,13 @@ export class Retrier {
}

// if the result is not a promise then reject an error
if (!(result instanceof Promise)) {
if (!result || typeof result.then !== "function") {
return Promise.reject(new Error("Result is not a promise."));
}

// call the original function and catch any ENFILE or EMFILE errors
// @ts-ignore because we know it's any
return result.catch(error => {
return Promise.resolve(result).catch(error => {
if (!this.#check(error)) {
throw error;
}
Expand Down Expand Up @@ -240,7 +240,9 @@ export class Retrier {

// otherwise, try again
task.lastAttempt = Date.now();
task.fn()

// Promise.resolve needed in case it's a thenable but not a Promise
Promise.resolve(task.fn())
// @ts-ignore because we know it's any
.then(result => task.resolve(result))

Expand Down
27 changes: 27 additions & 0 deletions tests/retrier.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,33 @@ describe("Retrier", () => {
assert.equal(result, 2);
});

it("should retry a function that rejects an error using a non-Promise thenable", async () => {

let count = 0;
const retrier = new Retrier(error => error.message === "foo");
const result = await retrier.retry(() => {
count++;

if (count === 1) {
return {
then() {
throw new Error("foo");
}
};
}

return {
then(fn) {
fn(count);
}
};
});

assert.equal(result, 2);
});



it("should retry a function that rejects an error multiple times", async () => {

let count = 0;
Expand Down

0 comments on commit 70f33c0

Please sign in to comment.