Skip to content

Instantly share code, notes, and snippets.

@oakley808
Last active July 20, 2017 22:02
Show Gist options
  • Save oakley808/b06d5d99dc896e916aa98945c6bcd8b6 to your computer and use it in GitHub Desktop.
Save oakley808/b06d5d99dc896e916aa98945c6bcd8b6 to your computer and use it in GitHub Desktop.
Redux-saga polling recipe with concurrency and canceling
// runs on load
export function* main() {
const pollingInstance = yield fork(pollingWatcher);
// fork other watchers ...
// if location changes, kill the watcher(s)
yield take(LOCATION_CHANGE);
yield cancel(pollingInstance);
// cancel other watchers ...
}
// Listen for every START and fork off saga that will start/stop polling
export function* pollingWatcher() {
yield fork(takeEvery, START, pollRacer);
}
export function* pollRacer(raceAction) {
const { response, cancelPolling } = yield race({
response: call(pollingSaga, raceAction),
cancelPolling: take(action => (action.type.endsWith('CANCEL') && action.payload.data.id === raceAction.payload.data.id))
});
}
// try polling every 3 seconds until the server completes or errors out
// put success or failure actions
export function* pollingSaga(action) {
try {
const { id } = action.payload.data;
let status = 'p';
let pollResponse;
while (status !== 'complete') {
yield call(delay, 3000);
pollResponse = yield call(request, someUrl, id);
status = pollResponse.data && pollResponse.data.status;
if (status === 'error') throw new Error('Runtime error');
}
yield put(pollSuccess(pollResponse.data));
} catch (error) {
yield put(pollFailure(error));
} finally {
if (yield cancelled()) {
console.log('pollingSaga cancelled');
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment