110Implement a resilient polling engine with exponential backoff, visibility awareness, timeout, and cancellation
Problem
A naive setInterval(fetchStatus, 2000) overlaps slow requests, hammers a failing server, and keeps polling in background tabs. Implement createPoller(task, options) returning { start(), stop(), isRunning }:
task({ signal })is async; its result goes toonData(result), its error toonError(error).- No overlap: the next call starts only after the previous one finished plus a delay.
- Backoff: after a success, wait
interval; after the n-th consecutive failure, waitmin(maxInterval, interval * backoffFactor ** n). Report every chosen delay withonSchedule(delay). - Timeout: abort a call that runs longer than
timeoutms (its signal aborts with aTimeoutError), count it as a failure and continue, even if the task ignores the signal. - Visibility:
visibilityis{ isHidden(), onChange(callback) → unsubscribe }. Do not start calls while hidden. When the page becomes visible again, poll immediately. - Cancellation:
stop()aborts the in-flight call, cancels any wait, and guarantees no further calls or callbacks.
Defaults: interval = 1000, maxInterval = 30000, backoffFactor = 2, timeout = 10000, onData, onError and onSchedule no-ops, and visibility based on document.visibilityState.
Try it yourself
Write your solution, run it, then submit to check it against the tests.
Press Run or ⌘ Enter to execute your code.
Step-by-step
Write async function loop(): while running, call the task, then wait. setTimeout chained after each call (instead of setInterval) is what makes overlap impossible.
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 5 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.