diff --git a/README.md b/README.md index 3a46af7..8b23cd6 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ poll(() => superagent.get('http://google.com'), 1000) .then(() => console.log("You're connected to the internet!")) ``` -## `poll(fn, interval)` +## `poll(fn, interval, [options])` Begins calling `fn` every `interval` milliseconds until the condition passes (which defaults to `fn` didn't throw an `Error` or return a rejected `Promise`). @@ -56,3 +56,5 @@ You can specify a timeout (in milliseconds) by calling `.timeout` on the returne ```js poll(...).timeout(30000) // time out after 30 seconds ``` + +If you call `.noWrapError()` on the returned `Promise`, it won't wrap rejection errors. \ No newline at end of file diff --git a/src/index.js b/src/index.js index c25b8f4..aad6d7a 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,7 @@ export type Poller = Promise & { cancel(): void; until(condition: UntilCondition): Poller; timeout(ms: number): Poller; + noWrapError(): Poller; } export type CallContext = { @@ -14,10 +15,9 @@ export type CallContext = { fail(error: Error): void; pass(value: T): void; } - function poll( fn: (info: CallContext) => T | Promise, - interval: number + interval: number, ): Poller { let fail, pass let attemptNumber = 0 @@ -25,6 +25,7 @@ function poll( let timeout: ?number let timeoutId: ?any let lastError: ?Error + let wrapError: boolean = true if (!Number.isFinite(interval) || interval < 0) { throw new Error(`invalid interval: ${interval}`) @@ -65,8 +66,12 @@ function poll( const nextTime = now + interval if (timeout != null && nextTime - startTime > timeout) { let message = "timed out waiting for polling to succeed" - if (lastError) message += `; last error: ${lastError.stack}` - reject(new Error(message)) + if (wrapError) { + if (lastError) message += `; last error: ${lastError.stack}` + reject(new Error(message)) + } else { + reject(lastError || new Error(message)) + } } else { const delay = Math.max(0, nextTime - Date.now()) timeoutId = setTimeout(attempt, delay) @@ -86,6 +91,10 @@ function poll( timeout = ms return promise } + ;(promise: any).noWrapError = () => { + wrapError = false + return promise + } return (promise: any) } diff --git a/test/index.js b/test/index.js index 891acb9..b9fe9b7 100644 --- a/test/index.js +++ b/test/index.js @@ -38,6 +38,17 @@ describe('poll', function () { expect(error.message).to.match(/timed out/i) expect(error.message).to.match(/last error: Error: test!/i) }) + it(`doesn't wrap error if wrapError: false`, async () => { + let numAttempts + let error + await poll(({attemptNumber, elapsedTime}: CallContext) => { + numAttempts = attemptNumber + 1 + if (elapsedTime < 500) throw new Error('test!') + }, 100).timeout(250).noWrapError().catch(err => error = err) + expect(numAttempts).to.equal(3) + if (!error) throw new Error('expected error to be thrown') + expect(error.message).to.equal('test!') + }) it('allows fn to manually pass', async () => { const result = await poll(({attemptNumber, pass}: CallContext): any => { if (attemptNumber === 3) pass(attemptNumber)