Blog>
Snippets

Redux-Saga Retry with Cancellation

A Redux-Saga example where a retry sequence for an XHR call can be cancelled by a specific user action, demonstrating cancellation in retry logic.
import { call, put, take, cancel, fork, cancelled } from 'redux-saga/effects';
import { retry } from 'redux-saga/effects';
import { fetchSomeData } from './api'; // Import your async function
import { FETCH_REQUEST, CANCEL_FETCH, fetchDataSuccess, fetchDataFailure } from './actions';
Imports necessary effects from redux-saga and functions/actions from other files.
function* fetchWithRetry(action) {
  try {
    const retryCount = 3;
    const retryDelay = 2000;
    const data = yield retry(retryCount, retryDelay, fetchSomeData, action.payload);
    yield put(fetchDataSuccess(data));
  } catch (error) {
    yield put(fetchDataFailure(error.toString()));
  } finally {
    if (yield cancelled()) {
      // Handle cancellation logic here,
      // for example, you might want to abort the fetch request
    }  
  }
}
Defines a Saga that attempts to fetch data with retries. It tries the specified number of times with delays between attempts. If the saga is cancelled, it enters the finally block where cancellation specific logic can be executed.
function* watchFetchData() {
  while (true) {
    const fetchTask = yield take(FETCH_REQUEST);
    const bgFetchTask = yield fork(fetchWithRetry, fetchTask);
    const action = yield take([CANCEL_FETCH, FETCH_REQUEST]);
    if (action.type === CANCEL_FETCH) {
      yield cancel(bgFetchTask);
    }
  }
}
Watches for fetch data requests and forks a new task to handle the fetch with retry. If a cancel action is dispatched, it cancels the ongoing fetch task.