【问题标题】:a way to know when Angular $http is "requesting"一种知道 Angular $http 何时“请求”的方法
【发布时间】:2013-03-09 21:33:57
【问题描述】:

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

有没有办法知道$http 还没有回复?我现在这样做的方式是我的控制器中有一个名为 $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;
            }
        );
    }
}

【问题讨论】:

  • +1 我做同样的事情,但在完成与成功或错误时关闭请求。目前想不出更好的方法。
  • This 似乎是您正在寻找的东西。我懒得测试它并将其变成正确的答案。也许您可以发布最终结果作为答案。
  • @TrevorSenior 很高兴知道,我不是唯一一个这样做的人。德米特里的回答似乎很有希望。昏昏欲睡,行为肯定存在,只是比我目前的解决方案复杂一点
  • @Ronnie 当您询问“$http 提供的任何内容”时,您所谈论的正是$httpProvider。我也觉得这很复杂,但恐怕你得硬着头皮。

标签: javascript angularjs


【解决方案1】:

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

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

【讨论】:

  • 这似乎可行,除非根据docs.angularjs.org/api/ng.$http#pendingRequests pendingRequests 是“主要用于调试目的”,这有点令人沮丧。我想知道为什么
  • 是的,我同意你的观点,这句话也让我睡了。顺便说一句,这个 SO stackoverflow.com/questions/11786764/… 的答案包含所有需要的链接(尤其是这个 groups.google.com/forum/#!msg/angular/OroP1DBE6AA/dG4X3M_XvuAJ
  • 对不起,我是菜鸟。我从我的朋友那里听说,当您在应用程序中使用 websocket 时,然后您查看网络,它会显示一个持续/打开的请求/(或其他东西)。我想知道这个解决方案是否会将该 websocket 连接检测为待处理的请求。
  • 嗨@boi_echos。 Websockets 没有使用 http,因此不会显示为挂起的请求。
  • 如何查看 $resource 服务的待处理请求?我知道 $resource 在内部使用 $http 但这在我的情况下不起作用。我正在尝试在打字稿中创建指令来检查待处理的请求。检查这个问题stackoverflow.com/questions/38226567/…
【解决方案2】:

这里没有一个答案真正适合我,我避免使用$http.pendingRequests,所以这就是我所做的

我的用例是,如果我有任何正在进行的请求在服务器上执行操作,我必须在我的视口顶部显示一个简单的“正在加载..”消息。

.config 中,我注册了一个新的拦截器。在里面我添加了一个简单的计数器,每次请求递增 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;
       }
    };
}]);

【讨论】:

    【解决方案3】:

    这个jsbin project 将@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;
    }
    

    【讨论】:

      【解决方案4】:

      试试这个指令: 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);
          })
      
      
        });
      

      描述:

      • 正在加载&lt;!--1.attach the directive--&gt;
      • loading="loading" &lt;!--2.write the scope.loading to the app.$rootScope--&gt;
      • data-visible="{{loading}}" &lt;!--2.read loading props for CSS--&gt;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-21
        • 1970-01-01
        • 1970-01-01
        • 2017-11-28
        • 2019-02-08
        • 2012-05-08
        • 1970-01-01
        相关资源
        最近更新 更多