Skip to content

Instantly share code, notes, and snippets.

@ScottGuymer
Created March 26, 2014 15:31
Show Gist options
  • Save ScottGuymer/9786082 to your computer and use it in GitHub Desktop.
Save ScottGuymer/9786082 to your computer and use it in GitHub Desktop.
Angular $http interceptor to allow for a loading spinner whenever any ajax request is made. Could be extended to provide request logging and error handling.
<div id="loadingWidget" loading-widget>
<div class="loadingContent">
<p>
Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....Loading....
</p>
</div>
</div>
'use strict';
// Declare module which depends on filters, and services
angular.module('notificationWidget', [])
// set up the interceptor
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q, $injector) {
var notificationChannel,
$http;
return {
// optional method
'request': function (config) {
// get requestNotificationChannel via $injector because of circular dependency problem
notificationChannel = notificationChannel || $injector.get('requestNotificationChannel');
// send a notification requests are complete
notificationChannel.requestStarted();
// do something on success
return config || $q.when(config);
},
// optional method
'requestError': function (rejection) {
// get $http via $injector because of circular dependency problem
$http = $http || $injector.get('$http');
// don't send notification until all requests are complete
if ($http.pendingRequests.length < 1) {
// get requestNotificationChannel via $injector because of circular dependency problem
notificationChannel = notificationChannel || $injector.get('requestNotificationChannel');
// send a notification requests are complete
notificationChannel.requestEnded();
}
return $q.reject(rejection);
},
// optional method
'response': function (response) {
// get $http via $injector because of circular dependency problem
$http = $http || $injector.get('$http');
// don't send notification until all requests are complete
if ($http.pendingRequests.length < 1) {
// get requestNotificationChannel via $injector because of circular dependency problem
notificationChannel = notificationChannel || $injector.get('requestNotificationChannel');
// send a notification requests are complete
notificationChannel.requestEnded();
}
// do something on success
return response || $q.when(response);
},
// optional method
'responseError': function (rejection) {
// get $http via $injector because of circular dependency problem
$http = $http || $injector.get('$http');
// don't send notification until all requests are complete
if ($http.pendingRequests.length < 1) {
// get requestNotificationChannel via $injector because of circular dependency problem
notificationChannel = notificationChannel || $injector.get('requestNotificationChannel');
// send a notification requests are complete
notificationChannel.requestEnded();
}
console.log('There was an AJAX error - DO SOMETHING MORE HERE')
return $q.reject(rejection);
}
}
})
}])
// declare the notification pub/sub channel
.factory('requestNotificationChannel', ['$rootScope', function ($rootScope) {
// private notification messages
var _START_REQUEST_ = '_START_REQUEST_';
var _END_REQUEST_ = '_END_REQUEST_';
// publish start request notification
var requestStarted = function () {
$rootScope.$broadcast(_START_REQUEST_);
};
// publish end request notification
var requestEnded = function () {
$rootScope.$broadcast(_END_REQUEST_);
};
// subscribe to start request notification
var onRequestStarted = function ($scope, handler) {
$scope.$on(_START_REQUEST_, function (event) {
handler();
});
};
// subscribe to end request notification
var onRequestEnded = function ($scope, handler) {
$scope.$on(_END_REQUEST_, function (event) {
handler();
});
};
return {
requestStarted: requestStarted,
requestEnded: requestEnded,
onRequestStarted: onRequestStarted,
onRequestEnded: onRequestEnded
};
}])
// declare the directive that will show and hide the loading widget
.directive('loadingWidget', ['requestNotificationChannel', function (requestNotificationChannel) {
return {
restrict: "A",
link: function (scope, element) {
// hide the element initially
element.hide();
var startRequestHandler = function () {
// got the request start notification, show the element
element.show();
};
var endRequestHandler = function () {
// got the request start notification, show the element
element.hide();
};
// register for the request start notification
requestNotificationChannel.onRequestStarted(scope, startRequestHandler);
// register for the request end notification
requestNotificationChannel.onRequestEnded(scope, endRequestHandler);
}
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment