![]()
In AngularJS, retrying failed HTTP requests automatically is a common requirement, especially when dealing with intermittent network issues or server-side errors. For this purpose, you can use $httpInterceptor in combination with AngularJS’s $q service to implement automatic retries. By setting up an HTTP interceptor, you can monitor request failures and retry them a specific number of times before failing definitively.
1. Why Automatically Retry Failed HTTP Requests?
Automatic retries are useful in situations where:
- Network conditions are unstable: Sometimes requests fail due to temporary network issues.
 - Server-side delays or throttling: If the server is temporarily unavailable or experiencing high load.
 - Intermittent errors: A retry strategy can mitigate issues like rate limiting, temporary server errors, or transient connectivity issues.
 
2. Implementing Automatic Retries
To retry HTTP requests, you need to intercept failed requests using $httpInterceptor and define a retry strategy based on the HTTP status code, network condition, or any custom condition.
3. Steps to Implement Automatic Retries
Step 1: Create the Retry Logic Interceptor
First, you need to create an interceptor that will catch the failed HTTP requests and retry them.
angular.module('myApp', [])
  .factory('retryInterceptor', function($q, $timeout) {
    // The maximum number of retry attempts
    const MAX_RETRIES = 3;
    // The delay (in ms) between retries
    const RETRY_DELAY = 1000;
    // Keep track of the number of retries
    function retryRequest(retryCount, config) {
      if (retryCount >= MAX_RETRIES) {
        return $q.reject(config);
      }
      // Increment the retry count
      retryCount++;
      // Retry the request after a delay
      return $timeout(function() {
        config.retryCount = retryCount;
        return $http(config);
      }, RETRY_DELAY);
    }
    return {
      // Request interceptor (for adding retryCount)
      request: function(config) {
        config.retryCount = 0; // Start with 0 retry count
        return config;
      },
      // Response interceptor (to handle retries)
      responseError: function(rejection) {
        const config = rejection.config;
        const retryCount = config.retryCount || 0;
        // Retry logic: Only retry for certain HTTP status codes, e.g., 500 or 503
        if (retryCount < MAX_RETRIES && (rejection.status === 500 || rejection.status === 503)) {
          return retryRequest(retryCount, config);
        }
        // Reject if max retries exceeded or status code isn't appropriate
        return $q.reject(rejection);
      }
    };
  });
Step 2: Register the Interceptor
Once the retry logic is implemented, you need to register the retryInterceptor globally within your AngularJS application.
angular.module('myApp', [])
  .config(function($httpProvider) {
    // Register the interceptor globally
    $httpProvider.interceptors.push('retryInterceptor');
  });
Step 3: Example Usage
Now, every HTTP request made by your AngularJS application will be subject to this retry logic. For example, you can use it to call an API:
angular.module('myApp')
  .controller('ApiController', function($scope, $http) {
    $scope.fetchData = function() {
      $http.get('/api/data')
        .then(function(response) {
          // Handle successful response
          console.log('Data fetched:', response.data);
        })
        .catch(function(error) {
          // Handle the final error after retries
          console.error('Failed to fetch data:', error);
        });
    };
  });
In the above example, the request will automatically retry up to 3 times if it fails with a 500 or 503 error code. The retry attempt will be delayed by 1 second (RETRY_DELAY), and after 3 retries, if the request still fails, it will be rejected, and an error will be logged.
4. Customizing Retry Logic
You can further customize the retry logic based on your application’s needs:
- Retry on specific HTTP status codes: You can retry on a specific set of status codes (e.g., 500, 503, or 408).
 - Exponential backoff: Instead of using a fixed delay between retries, you can implement an exponential backoff strategy where the delay increases with each retry.
 - Custom retry conditions: You can also check other conditions before retrying, such as the number of requests sent, the type of request (GET, POST), or network conditions.
 
Here’s an example of exponential backoff:
angular.module('myApp', [])
  .factory('retryInterceptor', function($q, $timeout) {
    const MAX_RETRIES = 5;
    const INITIAL_DELAY = 1000; // 1 second delay
    function retryRequest(retryCount, config) {
      if (retryCount >= MAX_RETRIES) {
        return $q.reject(config);
      }
      // Exponential backoff
      const delay = INITIAL_DELAY * Math.pow(2, retryCount);
      return $timeout(function() {
        config.retryCount = retryCount;
        return $http(config);
      }, delay);
    }
    return {
      request: function(config) {
        config.retryCount = 0;
        return config;
      },
      responseError: function(rejection) {
        const config = rejection.config;
        const retryCount = config.retryCount || 0;
        if (retryCount < MAX_RETRIES && (rejection.status === 500 || rejection.status === 503)) {
          return retryRequest(retryCount, config);
        }
        return $q.reject(rejection);
      }
    };
  });
5. Advantages of Automatic Retries
- Improved User Experience: Automatic retries can provide a smoother user experience by minimizing interruptions caused by transient errors.
 - Handling Temporary Server Issues: If a request fails due to temporary server issues (like 503 Service Unavailable), retrying the request can often succeed after a short delay.
 - Network Resilience: In environments where the network can be unreliable (e.g., mobile applications), automatic retries improve reliability.
 
6. Disadvantages and Considerations
- Overloading the Server: If too many retries are made in a short time, it could overload the server or make the problem worse.
 - Infinite Retries: If the retry logic isn’t properly managed, you could end up in an infinite retry loop. Always set a maximum retry limit.
 - Exponential Backoff: If using exponential backoff, you need to ensure that delays don’t create a bad user experience due to long wait times.
 
