Angular's builtin $http
service allows us to send HTTP requests. Oftentime, the need arise to do things before or after a request, for example adding to each request an authentication token or creating a generic error handling logic.
Create an HTML file with the following content:
<!DOCTYPE html>
<html>
<head>
<title>Angular Interceptor Sample</title>
<script src="https://code.angularjs.org/1.5.8/angular.min.js"></script>
<script src="app.js"></script>
<script src="appController.js"></script>
<script src="genericInterceptor.js"></script>
</head>
<body ng-app="interceptorApp">
<div ng-controller="appController as vm">
<button ng-click="vm.sendRequest()">Send a request</button>
</div>
</body>
</html>
Add a JavaScript file called 'app.js':
var interceptorApp = angular.module('interceptorApp', []);
interceptorApp.config(function($httpProvider) {
$httpProvider.interceptors.push('genericInterceptor');
});
Add another one called 'appController.js':
(function() {
'use strict';
function appController($http) {
var vm = this;
vm.sendRequest = function(){
$http.get('http://google.com').then(function(response){
console.log(response);
});
};
}
angular.module('interceptorApp').controller('appController',['$http', appController]);
})();
And finally the file containing the interceptor itself 'genericInterceptor.js':
(function() {
"use strict";
function genericInterceptor($q) {
this.responseError = function (response) {
return $q.reject(response);
};
this.requestError = function(request){
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
};
this.response = function(response){
return response;
};
this.request = function(config){
return config;
}
}
angular.module('interceptorApp').service('genericInterceptor', genericInterceptor);
})();
The 'genericInterceptor' cover the possible functions which we can override adding extra behavior to our application.
In the base html (index.html) where we usually include the angular scripts or the html that is shared across the app, leave an empty div element, the flash messages will be appearing inside this div element
<div class="flashmessage" ng-if="isVisible">
{{flashMessage}}
</div>
In the config method of angular module, inject the httpProvider, the httpProvider has an interceptor array property, push the custom interceptor, In the current example the custom interceptor intercepts only the response and calls a method attached to rootScope.
var interceptorTest = angular.module('interceptorTest', []);
interceptorTest.config(['$httpProvider',function ($httpProvider) {
$httpProvider.interceptors.push(["$rootScope",function ($rootScope) {
return { //intercept only the response
'response': function (response)
{
$rootScope.showFeedBack(response.status,response.data.message);
return response;
}
};
}]);
}])
Since only providers can be injected into the config method of an angular module (that is httpProvider and not the rootscope), declare the method attached to rootscope inside the run method of angular module.
Also display the message inside $timeout so that the message will have the flash property, that is disappearing after a threshold time. In our example its 3000 ms.
interceptorTest.run(["$rootScope","$timeout",function($rootScope,$timeout){
$rootScope.showFeedBack = function(status,message){
$rootScope.isVisible = true;
$rootScope.flashMessage = message;
$timeout(function(){$rootScope.isVisible = false },3000)
}
}]);
Trying to inject $rootScope or any other services inside config method of angular module, the lifecycle of angular app doesnt allow that and unknown provider error will be thrown. Only providers can be injected in config method of the angular module