Skip to content

Instantly share code, notes, and snippets.

@oshikryu
Last active December 6, 2019 20:47
Show Gist options
  • Save oshikryu/9cc853b5f4cdfdca3f6348c996bf9bec to your computer and use it in GitHub Desktop.
Save oshikryu/9cc853b5f4cdfdca3f6348c996bf9bec to your computer and use it in GitHub Desktop.
polling-endpoint-saga
import * as types from './types';
export const watchPollEndpoint = () => {
return {
types: types.WATCH_POLL_ENDPOINT,
}
}
export const stopPolling = () => {
return {
types: types.STOP_POLLING,
}
}
export const setItems = (items) => {
return {
types: types.SET_ITEMS,
items,
}
}
export default const pollReducer(state={}, action) {
switch (action.type) {
case SET_ITEMS:
return {
items: action.items
}
default:
return state
}
}
import { put, call, fork, takeLatest, cancel } from 'redux-saga/effects';
import * as actions from './actions';
import * as types from './types';
const POLLING_DELAY = 3000;
/**
* Explicitly cancelling a provided task
*
* @param {Task} pollTask
* @method *cancelPolling
*/
export function *cancelPolling(pollTask) {
yield cancel(pollTask);
}
/**
* This method makes an API call to an endpoint within a try/catch and stops polling if the
* endpoint returns in an error state.
*
* Cancelling polling ensures that repeated bad calls (404/500) won't continue to hammer the server
*
* @method *pollAPICall
*/
export function *pollAPICall() {
try {
const res = yield call('/my-poll-endpoint');
yield put(actions.setItems(res));
} catch (e) {
console.error(e);
yield put(actions.stopPolling());
}
}
/**
* This method sets up a continuous loop to make an API request with a delay after the API call
* returns
*
* @method *pollEndpointLoop
*
*/
export function *pollEndpointLoop() {
while (true) {
try {
yield fork(pollAPICall);
// optional delay
yield call(delay, POLLING_DELAY);
} catch(e) {
console.error(e);
}
}
}
/**
* This method initializes the polling loop that does two things:
*
* 1. creates a forked task from the poll API call
* 2. passes in the forked task as an argument to a watching function that will cancel a task given a certain condition (i.e. an action to stopPolling is called)
*
* @method pollOrCancelEndpoint
*/
export function *pollOrCancelEndpoint() {
const pollTask = yield fork(pollEndpointLoop);
yield watchCancelPoll(pollTask);
}
/* WATCHER FUNCTIONS */
export function *watchCancelPoll(pollTask) {
yield takeLatest(types.STOP_POLLING, () => cancelPolling(pollTask));
}
export function *watchPoll() {
yield takeLatest(types.WATCH_POLL_ENDPOINT, pollOrCancelEndpoint);
}
/**
* Call this method to initiate a redux-saga based polling function with an optional cancel state
*
* @method pollingSaga
*/
export default function *pollingSaga() {
yield watchPoll();
}
export const STOP_POLLING = 'stop-polling';
export const WATCH_POLL_ENDPOINT = 'watch-poll-endpoint';
export const SET_ITEMS = 'set-items';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment