Blog>
Snippets

Exponential Backoff in Saga Retry

Implementing an exponential backoff strategy in Redux-Saga for retrying an XHR call, to progressively increase the delay between retries.
import { call, put } from 'redux-saga/effects';

function* fetchWithRetry(url, options, maxRetries = 3) {
  let tries = 0;
  while (tries < maxRetries) {
    try {
      const response = yield call(fetch, url, options);
      // Assuming a successful response has a status in the range 200-299
      if (!response.ok) {
        throw new Error('Non-200 response');
      }
      return response;
    } catch (error) {
      if (tries === maxRetries - 1) {
        throw error;
      }
      // Exponential backoff formula: delay = 2^attemptNumber * 1000 (ms)
      const delay = Math.pow(2, tries) * 1000;
      yield call(wait, delay);
      tries++;
    }
  }
}

// Helper function to pause the saga for a given amount of time
function wait(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
This code snippet defines a fetchWithRetry saga where fetch calls are retried with an exponential backoff. After each failed attempt, it waits for 2^tries * 1000 milliseconds before trying again. The wait function is a helper that creates a Promise that resolves after a given timeout, effectively pausing the saga. You can use this saga by passing in the URL and options for your fetch call along with an optional maxRetries parameter to limit the number of attempts.