Skip to content

Commit 0f7e4f5

Browse files
committed
Use Infinity in retry. Do not fail on returned Error. Update README.
1 parent f3cd1fd commit 0f7e4f5

File tree

3 files changed

+46
-25
lines changed

3 files changed

+46
-25
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Then somewhere in your node.js application:
4242
* [`series`](#series)
4343
* [`timeout`](#timeout)
4444
* [`whilst`](#whilst), `doWhilst`
45+
* [`retry`](#retry)
4546

4647

4748
# Utilities
@@ -161,3 +162,37 @@ Example:
161162
.then(function(result) {
162163
// result will be 10 here.
163164
});
165+
166+
<a name="retry"/>
167+
### retry(options, fn)
168+
169+
Will continuously call `fn` until it returns a synchronous value, doesn't throw, or returns a Promise that resolves. It will be retried `options.times`. You can pass `{times: Infinity}` to retry indefinitely. The `fn` will be passed the `lastAttempt` object which is the Error object of the last attempt.
170+
171+
Options: `times` (Default=5) and `interval` (Default=0). `interval` is the time between retries in milliseconds. If the `options` argument is passed as just a number, only `times` will be set.
172+
173+
Examples:
174+
175+
var count = 0;
176+
promiseTools.retry({times: 4, interval: 5}, function(lastAttempt) {
177+
count++;
178+
if (count === 2) Promise.resolve(true);
179+
else Promise.reject(new Error('boom'));
180+
})
181+
.then(function(result) {
182+
// result will be `true` here.
183+
});
184+
185+
---------------------------------------------
186+
187+
var count = 0;
188+
promiseTools.retry(1, function(lastAttempt) {
189+
count++;
190+
if (count === 2) Promise.resolve(true);
191+
else Promise.reject(new Error('boom'));
192+
})
193+
.then(function(result) {
194+
// will not resolve.
195+
})
196+
.catch(function(err) {
197+
// err.message should be `boom` here.
198+
});

src/index.js

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,6 @@ exports.doWhilst = (fn, test) => {
191191
return exports.whilst(doTest, fn);
192192
};
193193

194-
exports.FOREVER = -1;
195-
196194
/*
197195
* keep calling `fn` until it returns a non-error value, doesn't throw, or returns a Promise that resolves. `fn` will be
198196
* attempted `times` many times before rejecting. If `times` is given as `exports.FOREVER`, then `retry` will attempt to
@@ -206,8 +204,8 @@ exports.FOREVER = -1;
206204
exports.retry = (options, fn) => {
207205
let times = 5;
208206
let interval = 0;
209-
let attempts = [];
210-
let infinite = false;
207+
let attempts = 0;
208+
let lastAttempt = null;
211209

212210
if ('number' === typeof(options)) {
213211
times = options;
@@ -220,22 +218,18 @@ exports.retry = (options, fn) => {
220218
throw new Error('Unsupported argument type for \'times\': ' + typeof(options));
221219
}
222220

223-
if (times === exports.FOREVER) infinite = true;
224-
225221
return new Promise((resolve, reject) => {
226222
let doIt = () => {
227223
Promise.resolve()
228224
.then(() => {
229-
return fn(attempts[attempts.length - 1]);
230-
})
231-
.then((results) => {
232-
if (results instanceof Error) throw results;
233-
else resolve(results);
225+
return fn(lastAttempt);
234226
})
227+
.then(resolve)
235228
.catch((err) => {
236-
attempts.push(err);
237-
if (!infinite && attempts.length === times) {
238-
reject(attempts);
229+
attempts++;
230+
lastAttempt = err;
231+
if (times !== Infinity && attempts === times) {
232+
reject(lastAttempt);
239233
} else {
240234
setTimeout(doIt, interval);
241235
}

test/retry.js

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ describe('retry', () => {
2020
});
2121

2222
it('should retry infinitely and resolve', () => {
23-
let retry = promiseTools.retry(-1, getTest(3));
23+
let retry = promiseTools.retry(Infinity, getTest(3));
2424
return expect(retry).to.eventually.equal(3);
2525
});
2626

2727
it('should reject', (done) => {
2828
let retry = promiseTools.retry(3, getTest(4));
29-
retry.catch((attempts) => {
29+
retry.catch((lastAttempt) => {
3030
try {
31-
expect(attempts.length).to.eq(3);
31+
expect(lastAttempt).to.be.instanceof(Error);
3232
done();
3333
} catch (err) {
3434
done(err);
@@ -58,12 +58,4 @@ describe('retry', () => {
5858
});
5959
expect(p).to.eventually.be.rejectedWith('Unsupported argument type for \'times\': undefined');
6060
});
61-
62-
it('should reject when an Error value is resolved', () => {
63-
let retry = promiseTools.retry(1, () => {
64-
return new Error('boom');
65-
});
66-
return expect(retry).to.eventually.be.rejectedWith('boom');
67-
});
68-
6961
});

0 commit comments

Comments
 (0)