способ узнать, когда Angular $ http «запрашивает»

17

Я делаю запрос $http , когда пользователь нажимает <button> , и я отключаю / скрываю / показываю несколько элементов на экране, пока запрос не вернется с success или error

Есть ли способ узнать, что $http еще не получил ответа? То, как я делаю это прямо сейчас, это то, что у меня есть var в моем контроллере, называемом $scope.requesting , который затем я использую на своей HTML-странице так:

<img src="img/loader.gif" ng-show="requesting" />

, так что в основном, когда $scope.requesting истинно, покажите вращающийся загрузчик ajaxyish.

Я хотел бы, если возможно, сбросить $scope.requesting и использовать любые $http , если они вообще есть.

Контроллер входа

function LoginForm($scope, $http)
{
    $scope.requesting = false;

    $scope.login = function()
    {
        $scope.requesting = true;

        $http.post('resources/request.php', data, {timeout:20000})
            .success(function(data, status, headers, config)
            {
                $scope.requesting = false;
            })
            .error(function(data, status, headers, config)
            {
                $scope.requesting = false;
            }
        );
    }
}
    
задан Ronnie 20.03.2013 в 17:39
источник
  • +1 Я делаю то же самое, но переключаю запрос на завершение с успехом или ошибкой. На данный момент нельзя думать о лучшем способе. –  x9hb8wcy6quezjk 20.03.2013 в 18:03
  • Это похоже на то, что вы ищете. Я слишком ленив, чтобы проверить его и превратить в правильный ответ. Возможно, вы можете опубликовать конечный результат в качестве ответа. –  drozzy 20.03.2013 в 18:11
  • @TrevorSenior хорошо хорошо знать, я не единственный, кто делает это именно так. Ответ Дмитрия кажется многообещающим. drozzy, поведение, безусловно, есть, чуть более сложное, чем мое текущее решение –  Ronnie 20.03.2013 в 18:19
  • @ Ronnie Когда вы спрашиваете о «любом $ http может предложить» - вы говорите именно о $ httpProvider. Я тоже думаю, что это сложно, но я боюсь, что вы должны укусить пулю. –  drozzy 20.03.2013 в 19:17

4 ответа

28

Вы можете использовать массив $http.pendingRequests объектов конфигурации для текущих ожидающих запросов. Это можно использовать так:

$scope.isLoading = function () {
   return $http.pendingRequests.length !== 0;
};
    
ответ дан Dmitry Evseev 20.03.2013 в 18:05
  • Кажется, что это сработает, за исключением того, что согласно docs.angularjs.org/api/ng.$http#pendingRequests pendingRequests «в первую очередь предназначено для использования в целях отладки», что отчасти обескураживает. интересно, почему –  Ronnie 20.03.2013 в 18:15
  • Да, я согласен с тобой, это замечание тоже засыпает. Btw просто наступил на этот SO stackoverflow.com/questions/11786764/... ответ на него содержит все необходимые ссылки (особенно this groups.google.com/forum/#!msg/angular/OroP1DBE6AA/dG4X3M_XvuAJ) –  Dmitry Evseev 20.03.2013 в 19:09
  • Извините за нооб. Я слышал от моего друга, что, когда вы используете веб-приложение в своем приложении, вы смотрите на сеть, он показывает непрерывный / открытый запрос / (или что-то еще). Интересно, будет ли это решение обнаруживать, что соединение с веб-сайтом рассматривается как ожидающий запрос или нет. –  boi_echos 02.10.2015 в 12:51
  • Привет @boi_echos. Веб-узлы не используют http и, следовательно, не будут отображаться как ожидающий запрос. –  Dmitry Evseev 04.10.2015 в 21:42
  • Как проверить ожидающий запрос для $ resource service? Я знаю, что $ resource внутренне использует $ http, но это не работает в моем случае. Я пытаюсь создать директиву в машинописном тексте, который проверяет ожидающий запрос. Проверьте этот вопрос stackoverflow.com/questions/38226567/... –  Microsoft Developer 06.07.2016 в 16:29
0

этот проект jsbin берет ответ @ DmitryEvseev на следующий шаг. Он обеспечивает более точный контроль над тем, какие запросы могут использоваться для запуска «загрузки ...».

Эти запросы с { showLoader: true } используются для отображения панели «Загрузка ...».

HTML

  <div ng-app="app">
    <div ng-controller="spinnerController as vm">
      <div ng-if="vm.isLoading()">Loading ...</div>
    </div>
  </div>

Javascript

angular
  .module('app', [])
  .config(config)
  .factory('httpLoader', httpLoader)
  .factory('httpLoaderInterceptor', httpLoaderInterceptor)
  .controller('spinnerController', spinnerController);

function config($httpProvider) {
  //adding the default http status code handler
  $httpProvider.interceptors.push('httpLoaderInterceptor');
}

function httpLoader() {
  var pendingReqs = {};
  var factory = {
    addPendingReq: addPendingReq,
    subtractPendingReq: subtractPendingReq,
    getPendingReqs: getPendingReqs
  };
  return factory;

  function addPendingReq(url) {
    console.log('adding url', url);
    pendingReqs[url] = true;
  }

  function subtractPendingReq(url) {

    console.log('removing url', url);
    delete pendingReqs[url];
  }

  function getPendingReqs() {
    return sizeOf(pendingReqs);
  }
}

function httpLoaderInterceptor($q, httpLoader) {

  var factory = {
    request: request,
    response: response,
    responseError: responseError
  };

  return factory;

  function request(config) {
    console.log('request', config.url);
    if (config.showLoader) {
      httpLoader.addPendingReq(config.url);
    }
    return config;
  }

  function response(res) {
    console.log('response', res.config.url);
    if (res.config.showLoader) {
      httpLoader.subtractPendingReq(res.config.url);
    }
  }

  function responseError(res) {
    console.log('responseError', res.config.url);
    if (res.config.showLoader) {
      httpLoader.subtractPendingReq(res.config.url);
    }
    return $q.reject(res);
  }
}

function spinnerController($http, httpLoader) {
  var self = this;
  self.isLoading = function() {
    return httpLoader.getPendingReqs() > 0;
  };

  $http.get('http://stackoverflow.com/posts/34561385',{
    showLoader: true
  });
  $http.get('http://www.amazon.com', {
    showLoader: true
  });
  $http.get('http://www.yahoo.com',{
    showLoader: true
  });
  $http.get('http://www.stackoverflow.com',{
    showLoader: true
  });
}

function sizeOf(obj) {
  var size = 0,
    key;
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      size++;
    }
  }
  return size;
}
    
ответ дан Henry Zou 02.01.2016 в 03:14
0

Попробуйте эту директиву: Ссылка

CSS

body {
  font-family: 'STHeiti', 'Microsoft YaHei', Helvetica, Arial, sans-serif;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}

.loading-widget {
  width: 100px;
  height: 100px;
  margin: auto;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: absolute;
}

.loading-widget,
.loading-widget[data-visible] {
  display: none;
}

.loading-widget[data-visible=true] {
  display: block;
}

.loading-widget img {
  width: 100%;
  height: 100%;
}

HTML:

<div class="loading-widget"
     isloading
     loading="loading"
     data-visible="{{loading}}"
>
  <img src="svg/default.svg" alt="">
</div>

JavaScript:

  angular.module('TestApp', ['nx.widget']);

  angular.module('TestApp').
  controller('MainCtrl', function ($http, $q, $rootScope) {
    $rootScope.loading = false;
    var s1 = $http.get('http://www.baidu.com');
    var s2 = $http.get('http://www.sina.com');
    var s3 = $http.get('http://www.163.com');
    var s4 = $http.get('http://www.qq.com');
    var s5 = $http.get('http://www.hao123.com');

    //you need a VPN if you're a Chinese(Thanks to the GFW)
    var s6 = $http.get('https://www.google.com/');


    $q.all([s1, s2, s3, s4, s5, s6]).then(function (responses) {
      console.log(responses);
    })


  });

Описание:

  • загружается <!--1.attach the directive-->
  • loading="loading" <!--2.write the scope.loading to the app.$rootScope-->
  • data-visible="{{loading}}" <!--2.read loading props for CSS-->
ответ дан Fei Zheng 17.05.2016 в 11:07
0

Ни один из ответов здесь не прибил его для меня, и я избегаю использования $http.pendingRequests , так что вот что я сделал

Мой вариант использования заключался в том, что я должен был показать простое сообщение «Загрузка ..» в верхней части моего окна просмотра, если бы у меня были какие-либо запросы на рейс, выполняемые на сервере.

Внутри .config , я зарегистрировал новый Interceptor. и внутри там я добавил простой счетчик, который увеличивается на 1 за каждый новый запрос и уменьшается на каждый ответ.

$httpProvider.interceptors.push([function () {
    var pendingRequestsCounter = 0;
    return {
        request: function (config) {
            pendingRequestsCounter++;
            if (pendingRequestsCounter > 0) {
                // we have some pending requests, so do something here 
            }
            return config;
        },
        response: function (response) {
            pendingRequestsCounter--;
            if (pendingRequestsCounter === 0) {
                // we have no pending requests, so do something else here 
            }
            return response;
       }
    };
}]);
    
ответ дан svarog 02.03.2017 в 14:12