Реализация загрузки спиннера с использованием httpInterceptor и AngularJS 1.1.5

Я нашел пример загрузки спиннера для вызовов http/resource здесь на SO:

Как видите, реализация работает (с использованием AngularJS 1.0.5). Однако, если вы измените источники на AngularJS 1.1.5. Пример больше не работает.

я узнал, что $httpProvider.responseInterceptors устарела в 1.1.5. Вместо этого следует использовать $httpProvider.interceptors

К сожалению, просто замена вышеуказанной строки в Plunker не решила проблему. Кто-нибудь когда-нибудь делал такой загрузочный спиннер, используя HttpInterceptor в AngularJS 1.1.5?

Спасибо за вашу помощь!

Майкл

3 ответа

Решение

Благодаря подсказке Стива я смог реализовать загрузчик:

перехватчик:

.factory('httpInterceptor', function ($q, $rootScope, $log) {

    var numLoadings = 0;

    return {
        request: function (config) {

            numLoadings++;

            // Show loader
            $rootScope.$broadcast("loader_show");
            return config || $q.when(config)

        },
        response: function (response) {

            if ((--numLoadings) === 0) {
                // Hide loader
                $rootScope.$broadcast("loader_hide");
            }

            return response || $q.when(response);

        },
        responseError: function (response) {

            if (!(--numLoadings)) {
                // Hide loader
                $rootScope.$broadcast("loader_hide");
            }

            return $q.reject(response);
        }
    };
})
.config(function ($httpProvider) {
    $httpProvider.interceptors.push('httpInterceptor');
});

Директива:

.directive("loader", function ($rootScope) {
    return function ($scope, element, attrs) {
        $scope.$on("loader_show", function () {
            return element.show();
        });
        return $scope.$on("loader_hide", function () {
            return element.hide();
        });
    };
}
)

CSS:

#loaderDiv {
   position: fixed;
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
   z-index: 1100;
   background-color: white;
   opacity: .6;
}

.ajax-loader {
   position: absolute;
   left: 50%;
   top: 50%;
   margin-left: -32px; /* -1 * image width / 2 */
   margin-top: -32px; /* -1 * image height / 2 */
   display: block;
}

HTML:

<div id="loaderDiv" loader>
    <img src="src/assets/img/ajax_loader.gif" class="ajax-loader"/>
</div>

"responseInterceptors" устарел. "Перехватчики" заменили его множеством улучшений в предварительной версии. Сверху головы, я не помню, какая версия. Документация по этому вопросу невелика, поэтому вам, вероятно, лучше всего изучить исходный код.

Суть изменений выглядит следующим образом:

$httpProvider.interceptors.push(function($q, $rootScope) {
  return {
     'request': function(config) {
        // intercepts the request
     },
     'response': function(response) {
       // intercepts the response. you can examine things like status codes
     },
     'responseError': function(response) {
       // intercepts the response when the response was an error
     }
  }
});

В угловом источнике вы найдете документацию в разделе "* # Перехватчики" в функции $HttpProvider. Существует пример использования, очень похожий на тот, который я опубликовал выше.

Предоставленное / принятое решение отлично, если вы хотите включить JQuery в свое решение, которое команда AngularJS рекомендует не продвигать. element.show/.hide не поддерживается в JQLite Angular.... Поэтому для работы в сеансе не-jquery необходимы следующие рефакторы:

Измените элемент HTML, чтобы добавить класс "скрытый"

<div id="loaderDiv" loader class="hidden">
     <img src="Content/images/yourgif.gif" class="ajax-loader" />
</div>

Добавьте скрытый класс к вашему CSS:

.hidden{display:none !important}

И подправить директиву так:

(function() {
    'use strict';

    angular
        .module('your_app')
        .directive('yourSpinner', yourSpinner);

    yourSpinner.$inject = ['$rootScope'];

    function yourSpinner($rootScope) {
       return function($scope, element, attrs) {
           $scope.$on("loader_show", function () {
               if (element.hasClass("hidden")) {
                   element.removeClass("hidden")
               }
            });
            return $scope.$on("loader_hide", function () {
                if(!element.hasClass("hidden")){
                    element.addClass("hidden")
                }
            });
        }
    }

})();

Фабрика в порядке, как есть.

Другие вопросы по тегам