Skip to content

Instantly share code, notes, and snippets.

@bettysteger
Last active August 27, 2018 06:24
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save bettysteger/db97ef64bfe2744ce589 to your computer and use it in GitHub Desktop.
Save bettysteger/db97ef64bfe2744ce589 to your computer and use it in GitHub Desktop.
Angular $httpProvider interceptor to handle requests and also cancels request on state change
/**
* This array is needed for canceling requests when changing the state/route.
* @type {Array}
*/
var currentRequests = [];
/**
* Handles route changes.
*/
app.run(['$rootScope', function($rootScope) {
/**
* Cancels pending requests
*/
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
angular.forEach(currentRequests, function(request) {
request.resolve(); // cancel
});
currentRequests = [];
});
}]);
/**
* Authentication with token and email for every server request. (Sets HTTP headers)
*
* This interceptor shows the error from the server (i18n key).
* Also sets global error variable if the request fails and redirects the user to '/' when he is not authorized.
* @see http://engineering.talis.com/articles/client-side-error-logging/
*/
app.factory('authInterceptor', ['$rootScope', '$q', '$cookies', '$location', '$timeout', function ($rootScope, $q, $cookies, $location, $timeout) {
return {
request: function (config) {
delete $rootScope.errorKey;
config.headers = config.headers || {};
config.headers['X-AUTH-TOKEN'] = $cookies['AUTH-TOKEN'];
config.headers['X-AUTH-EMAIL'] = $cookies['AUTH-EMAIL'];
if(!/\.html/.test(config.url)) {
var defer = $q.defer();
currentRequests.push(defer);
config.timeout = defer.promise;
}
return config;
},
responseError: function (response) {
var status = response.status;
// unauthorized -> redirect
if(status === 401) {
$rootScope.error = 'global.server_errors.unauthorized';
$timeout(function () {
$location.path('/');
}, 3000);
} else if(status !== 0) {
$rootScope.showErrorMsg = true; // general error message
$timeout(function() {
$rootScope.showErrorMsg = false;
}, 10000);
}
return $q.reject(response);
}
};
}]);
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
}]);
@bettysteger
Copy link
Author

HINT: Aborting requests on the client will NOT abort the requests on the server!

  • What you can do on the client side, however, is to cancel the callback execution. It can lead to some performance improvement, but the main advantage is to be sure to display the right information to the user.
  • If 2 requests are made in a short time, you can't be certain about the server response order. You might receive the second response first, and then receive the first response, leading to inconsistent data in your user interface.

Because there is not really a performance improvement, we decided to not cancel requests on the client - this code is just an example how you could do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment