一种知道Angular $http何时在“请求”的方法

a way to know when Angular $http is "requesting"

本文关键字:何时 请求 方法 http 一种 Angular      更新时间:2023-09-26

当用户单击<button>时,我发出$http请求,我禁用/隐藏/显示屏幕上的几个元素,直到请求返回successerror

有办法知道$http还没有回应吗?我现在的做法是在我的控制器中有一个名为$scope.requesting的变量然后在我的HTML页面中使用它,像这样:

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

$scope.requesting为true时,显示旋转的ajaxyish加载器

如果可能的话,我想放弃$scope.requesting,使用$http所提供的任何东西,如果有的话。

<<p> 登录控制器/strong>
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;
            }
        );
    }
}

您可以使用$http.pendingRequests配置对象数组来处理当前挂起的请求。可以这样使用:

$scope.isLoading = function () {
   return $http.pendingRequests.length !== 0;
};

这里的答案都不适合我,我也不喜欢使用$http.pendingRequests,所以下面是我所做的

我的用例是,如果我有任何正在运行的请求在服务器上做事情,我必须在我的视口顶部显示一个简单的"Loading.."消息。

.config内部,我已经注册了一个新的拦截器。我在里面添加了一个简单的计数器,每个请求加1,每个响应减1。

$httpProvider.interceptors.push([function () {
    var pendingRequestsCounter = 0;
    return {
        request: function (request) {
            pendingRequestsCounter++;
            if (pendingRequestsCounter > 0) {
                // we have some pending requests, so do something here 
            }
            return request;
        },
        response: function (response) {
            pendingRequestsCounter--;
            if (pendingRequestsCounter === 0) {
                // we have no pending requests, so do something else here 
            }
            return response;
       }
    };
}]);

这个jsbin项目采用@DmitryEvseev的答案进行下一步。它提供了更好的控制哪些请求可以用来触发"loading…"。

那些带有{ showLoader: true }的请求用于显示'loading…"面板。

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;
}

试试这个指令:https://github.com/afeiship/angular-isloading

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-->