Skip to content

Commit 958f78b

Browse files
committed
create a new promise utility library, taking retry code from uproxy
1 parent debae7b commit 958f78b

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/promises/promises.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// <reference path='../../../third_party/typings/es6-promise/es6-promise.d.ts' />
2+
/// <reference path='../../../third_party/typings/jasmine/jasmine.d.ts' />
3+
4+
import promises = require('./promises');
5+
6+
describe('retry', () => {
7+
const MAX_ATTEMPTS = 5;
8+
const RETURN_VALUE = 'hello';
9+
const REJECT_MESSAGE = 'goodbye';
10+
11+
it('only calls successful function once', (done) => {
12+
const f = jasmine.createSpy('spy');
13+
f.and.returnValue(Promise.resolve(RETURN_VALUE));
14+
promises.retry(f, MAX_ATTEMPTS).then((result: string) => {
15+
expect(f.calls.count()).toEqual(1);
16+
expect(result).toEqual(RETURN_VALUE);
17+
done();
18+
});
19+
});
20+
21+
it('calls multiple times until success', (done) => {
22+
const NUM_CALLS_BEFORE_SUCCESS = 3;
23+
let callCount = 0;
24+
const f = jasmine.createSpy('spy');
25+
f.and.callFake(() => {
26+
callCount++;
27+
if (callCount === NUM_CALLS_BEFORE_SUCCESS) {
28+
return Promise.resolve(RETURN_VALUE);
29+
} else {
30+
return Promise.reject('error');
31+
}
32+
});
33+
promises.retry(f, NUM_CALLS_BEFORE_SUCCESS + 1).then((result: string) => {
34+
expect(f.calls.count()).toEqual(NUM_CALLS_BEFORE_SUCCESS);
35+
expect(result).toEqual(RETURN_VALUE);
36+
done();
37+
});
38+
});
39+
40+
it('stops calling after the max number of failures', (done) => {
41+
const f = jasmine.createSpy('spy');
42+
f.and.returnValue(Promise.reject(new Error(REJECT_MESSAGE)));
43+
promises.retry(f, MAX_ATTEMPTS).catch((e: Error) => {
44+
expect(f.calls.count()).toEqual(MAX_ATTEMPTS);
45+
expect(e.message).toEqual(REJECT_MESSAGE);
46+
done();
47+
});
48+
});
49+
});

src/promises/promises.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='../../../third_party/typings/es6-promise/es6-promise.d.ts' />
2+
3+
// Invokes f up to maxAttempts number of times, resolving with its result
4+
// on the first success and rejecting on maxAttempts-th failure.
5+
export const retry = <T>(f: () => Promise<T>, maxAttempts: number): Promise<T> => {
6+
return f().catch((e:Error) => {
7+
--maxAttempts;
8+
if (maxAttempts > 0) {
9+
return retry(f, maxAttempts);
10+
} else {
11+
return Promise.reject(e);
12+
}
13+
});
14+
};

0 commit comments

Comments
 (0)