Last active
December 2, 2018 21:23
-
-
Save greyblake/9d9d6205ad1fd7cabd9cf259bea617de to your computer and use it in GitHub Desktop.
http-poll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { throwError, of, interval, Observable } from 'rxjs'; | |
import { take, filter, map, concatMap, catchError } from 'rxjs/operators'; | |
import { httpPoll, isNotReady } from './http-poll'; | |
function buildError(code) { | |
return { | |
error: { | |
errors: [{ code }] | |
} | |
}; | |
} | |
function buildPoll(call) { | |
let pollArgs = { | |
call, | |
delay: 0, | |
attempts: 10 | |
}; | |
return httpPoll(pollArgs); | |
} | |
describe('httpPoll', () => { | |
describe('when call function returns result', () => { | |
it('returns Observable that returns result', async () => { | |
let obs = buildPoll(() => of(5)); | |
let result = await obs.toPromise(); | |
expect(result).toEqual(5); | |
}); | |
}); | |
describe('when call function returns Observable that returns an error', () => { | |
it('propagates an error', async () => { | |
let obs = buildPoll(() => throwError(5)); | |
let isRejected = false; | |
try { | |
await obs.toPromise(); | |
} catch { | |
isRejected = true; | |
} | |
expect(isRejected).toEqual(true); | |
}); | |
}); | |
describe('when after sequence of NOT_READY a result is returned', () => { | |
it('returns a result', async () => { | |
let notReadyError = buildError('NOT_READY'); | |
let count = 0; | |
let obs = buildPoll( () => { | |
if (count > 5) { | |
return of('RESULT'); | |
} else { | |
count += 1; | |
return throwError(notReadyError); | |
} | |
}); | |
let result = await obs.toPromise(); | |
expect(result).toEqual('RESULT'); | |
}); | |
}); | |
describe('when time outed', () => { | |
it('propagates the last error', async () => { | |
let notReadyError = buildError('NOT_READY'); | |
let obs = buildPoll(() => throwError(notReadyError)); | |
let isRejected = false; | |
try { | |
await obs.toPromise(); | |
} catch { | |
isRejected = true; | |
} | |
expect(isRejected).toEqual(true); | |
}); | |
}); | |
}); | |
describe('isNotReady', () => { | |
it('return true for NOT_READY error', () => { | |
expect(isNotReady({})).toEqual(false); | |
expect(isNotReady('')).toEqual(false); | |
expect(isNotReady('12')).toEqual(false); | |
expect(isNotReady({error: ''})).toEqual(false); | |
expect(isNotReady(buildError('NOT_FOUND'))).toEqual(false); | |
expect(isNotReady(buildError('NOT_READY'))).toEqual(true); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { throwError, interval, Observable } from 'rxjs'; | |
import { take, concatMap, catchError } from 'rxjs/operators'; | |
interface PollArgs<T> { | |
call: () => Observable<T>, | |
delay: number, | |
attempts: number | |
} | |
export function httpPoll<T>({ call, delay, attempts }: PollArgs<T>): Observable<T> { | |
return interval(delay).pipe( | |
concatMap( (_) => call()), | |
catchError((err: any) => { | |
if (isNotReady(err) && attempts > 0) { | |
let newArgs = { call, delay, attempts: attempts - 1}; | |
return httpPoll(newArgs); | |
} else { | |
return throwError(err); | |
} | |
}), | |
take(1) | |
); | |
} | |
export function isNotReady(err: any): boolean { | |
return !!( | |
err | |
&& err.error | |
&& err.error.errors | |
&& err.error.errors[0] | |
&& err.error.errors[0].code === 'NOT_READY' | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment