Установите переменную rootScope в httpIntercept

Я хотел бы иметь возможность установить http-перехватчик AngularJS, который будет устанавливать $rootScope.loading в true или же falseв зависимости от того, выполняется ли в данный момент запрос AJAX.

Пока я собрал следующее:

angular.module('myApp')
.config(function ($httpProvider) {
  $httpProvider.responseInterceptors.push('loadingInterceptor');

  var loadingFunction = function (data, headersGetter) {
      $rootScope.loading = true

      return data;
  };
  $httpProvider.defaults.transformRequest.push(loadingFunction);
})
.factory('loadingInterceptor', function ($q, $window, $rootScope) {
    return function (promise) {
        return promise.then(function (response) {
            $rootScope.loading = false;
            return response;

        }, function (response) {
            $rootScope.loading = false;
            return $q.reject(response);
        });
    };
});

Но я не могу вводить $rootScope в блок конфигурации, поэтому у меня нет возможности установить $rootScope.loading переменная, когда начинается HTTP-запрос.

Я что-то здесь упускаю? Как мне это сделать?

3 ответа

responseInterceptors устарел http://docs.angularjs.org/api/ng.%24htt. Я улучшил предыдущий пример:

app.factory('myHttpInterceptor', ['$q', '$rootScope', '$injector',
    function ($q, $rootScope, $injector) {
        $rootScope.showSpinner = false;
        $rootScope.http = null;
        return {
            'request': function (config) {
                $rootScope.showSpinner = true;
                return config || $q.when(config);
            },
            'requestError': function (rejection) {
                $rootScope.http = $rootScope.http || $injector.get('$http');
                if ($rootScope.http.pendingRequests.length < 1) {
                    $rootScope.showSpinner = false;
                }
                if (canRecover(rejection)) {
                    return responseOrNewPromise
                }
                return $q.reject(rejection);
            },
            'response': function (response) {
                $rootScope.http = $rootScope.http || $injector.get('$http');
                if ($rootScope.http.pendingRequests.length < 1) {
                    $rootScope.showSpinner = false;
                }
                return response || $q.when(response);
            },
            'responseError': function (rejection) {
                $rootScope.http = $rootScope.http || $injector.get('$http');
                if ($rootScope.http.pendingRequests.length < 1) {
                    $rootScope.showSpinner = false;
                }
                if (canRecover(rejection)) {
                    return responseOrNewPromise
                }
                return $q.reject(rejection);
            }
        }
    }
]);

И вы можете использовать фабрику так:

app.config(function ($httpProvider) {
    $httpProvider.interceptors.push('myHttpInterceptor');
});

Вы можете вставлять только провайдеры в module.config, но вы все равно не должны делать это в преобразователях по умолчанию, вы должны делать это в перехватчиках (как вы делаете, когда устанавливаете load = false).

Может быть несколько запросов одновременно. Нечто подобное может работать:

angular.module('myApp')
  .config(function ($httpProvider) {
    $httpProvider.responseInterceptors.push(function ($rootScope) {
      $rootScope.numLoadings = 0;
      $rootScope.loading = false;
      return function (promise) {
        $rootScope.numLoadings++;
        $rootScope.loading = true;
        // make sure the loading screen is visible
        var hide = function (r) {
          if ((--$rootScope.numLoadings)===0){
            //console.log('hide the loading screen');
            $rootScope.loading = false;
          }
          return r;
        };
        return promise.then(hide, hide);
      };
    });
  });

Конечно, вам не нужно помещать numLoadings в корневую область, я просто поместил его для этого примера: http://plnkr.co/edit/32Mh9UOS3Z4vnOtrH9aR?p=preview

module.config имеет дело только с поставщиками, и вы не должны пытаться получить доступ к $ rootScope отсюда.

Кроме того, я не вижу причин для подсчета количества ожидающих запросов вручную, поскольку $http обслуживание и, ну... нет необходимости делать одну и ту же работу дважды:)

CoffeeScript

angular.module('app.services.networkStatusIndicator', []).config([

  '$httpProvider'

  ( $httpProvider )->

    # Network status indicator
    # ========================
    # Monitor XHTTP requests globally and update UI accordigly.

    $http = null
    interceptor = ['$q', '$injector', '$rootScope' , ($q, $injector, $rootScope )->
      success = (response)->
        $http = $http or $injector.get '$http'
        if $http.pendingRequests.length < 1
          $rootScope.networkStatus = 'idle'
        response

      error = (response)->
        $http = $http or $injector.get '$http'
        if $http.pendingRequests.length < 1
          $rootScope.networkStatus = 'idle'
        $q.reject response

      (promise)->
        $rootScope.networkStatus = 'loading'
        promise.then success, error
    ]
    $httpProvider.responseInterceptors.push interceptor
])

Javascript

angular.module('app.services.networkStatusIndicator', []).config([
  '$httpProvider', function($httpProvider) {
    var $http, interceptor;
    $http = null;
    interceptor = [
      '$q', '$injector', '$rootScope', function($q, $injector, $rootScope) {
        var error, success;
        success = function(response) {
          $http = $http || $injector.get('$http');
          if ($http.pendingRequests.length < 1) {
            $rootScope.networkStatus = 'idle';
          }
          return response;
        };
        error = function(response) {
          $http = $http || $injector.get('$http');
          if ($http.pendingRequests.length < 1) {
            $rootScope.networkStatus = 'idle';
          }
          return $q.reject(response);
        };
        return function(promise) {
          $rootScope.networkStatus = 'loading';
          return promise.then(success, error);
        };
      }
    ];
    return $httpProvider.responseInterceptors.push(interceptor);
  }
]);
Другие вопросы по тегам