Handling API errors efficiently is crucial for maintaining a smooth user experience in an AngularJS application. The $httpInterceptor
service allows you to globally intercept and modify HTTP requests and responses, making it an excellent choice for handling API errors centrally.
1. What is $httpInterceptor
?
An $httpInterceptor
is a factory function that allows you to modify HTTP requests and responses globally before they reach the server or the client. It helps in:
Logging API errors centrally
Showing user-friendly messages for failed requests
Retrying failed requests if needed
Redirecting users to the login page if authentication fails
2. Creating an $httpInterceptor
for API Error Handling
Step 1: Define the Interceptor
Create a new factory for $httpInterceptor
and inject it into your module.
angular.module('myApp')
.factory('httpErrorInterceptor', function($q, $injector) {
return {
// Intercept response errors
responseError: function(rejection) {
let $rootScope = $injector.get('$rootScope'); // Inject dynamically
let $state = $injector.get('$state'); // Get current state (for redirection)
console.error("HTTP Error:", rejection); // Log the error
// Handle different types of errors
if (rejection.status === 401) { // Unauthorized
$rootScope.$broadcast('unauthorized'); // Notify listeners
$state.go('login'); // Redirect to login page
}
else if (rejection.status === 403) { // Forbidden
alert("You don't have permission to access this resource.");
}
else if (rejection.status === 404) { // Not Found
alert("Requested resource not found.");
}
else if (rejection.status === 500) { // Internal Server Error
alert("Server error! Please try again later.");
}
return $q.reject(rejection); // Reject the promise with the error
}
};
});
Step 2: Register the Interceptor in the $httpProvider
After defining the interceptor, register it inside the .config()
block.
angular.module('myApp')
.config(function($httpProvider) {
$httpProvider.interceptors.push('httpErrorInterceptor');
});
Automatically intercepts all HTTP requests and responses
Handles API errors centrally
3. Displaying Global Error Messages Using $rootScope
If you want to show an error message whenever an API request fails, use $rootScope.$broadcast()
.
Step 1: Broadcast Errors from the Interceptor
Modify the interceptor to notify the entire app about errors.
.factory('httpErrorInterceptor', function($q, $rootScope) {
return {
responseError: function(rejection) {
$rootScope.$broadcast('httpError', rejection);
return $q.reject(rejection);
}
};
});
Step 2: Listen for API Errors in a Controller
Now, listen for API errors globally in the main controller.
angular.module('myApp')
.controller('MainController', function($scope) {
$scope.errorMessage = '';
$scope.$on('httpError', function(event, rejection) {
$scope.errorMessage = "API Error: " + rejection.statusText;
});
});
Shows error messages in the UI dynamically
4. Retrying Failed Requests Automatically
Sometimes, API calls fail due to temporary issues (e.g., network problems). You can retry failed requests automatically inside the interceptor.
Step 1: Modify the Interceptor to Retry Requests
.factory('httpRetryInterceptor', function($q, $injector, $timeout) {
return {
responseError: function(rejection) {
if (rejection.status === 500) { // Retry only on server errors
let $http = $injector.get('$http');
return $timeout(() => $http(rejection.config), 2000); // Retry after 2 seconds
}
return $q.reject(rejection);
}
};
});
Retries requests automatically if the server returns a 500
error
Uses $timeout()
to delay retry attempts
5. Redirecting to Login Page on Unauthorized (401) Responses
When a user’s session expires, APIs may return a 401 Unauthorized error. You can redirect users to the login page automatically when this happens.
Modify the Interceptor to Handle 401 Errors
.factory('authInterceptor', function($q, $injector) {
return {
responseError: function(rejection) {
if (rejection.status === 401) { // Unauthorized
let $state = $injector.get('$state');
$state.go('login'); // Redirect to login
}
return $q.reject(rejection);
}
};
});
Automatically redirects to login when authentication fails
6. Adding Authentication Tokens to Requests
For authenticated API requests, you need to attach an auth token (e.g., JWT) to the request headers.
Modify Requests to Include an Auth Token
.factory('authTokenInterceptor', function($q, AuthService) {
return {
request: function(config) {
let token = AuthService.getToken();
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
return config;
}
};
});
Ensures all API requests include an authentication token