【问题标题】:Angular synchronous http loop to update progress bar角同步http循环更新进度条
【发布时间】:2013-09-26 19:38:17
【问题描述】:

我正在尝试使用 foreach 中的顺序 http 请求更新进度条,这可行,但完成时它不是同步的,进度条正在通过 http 调用同步,我做错了什么?

angular.forEach(queue, function (item) {
    if (item.uid) {
        d.item = item;
        $http({
            url: BASE_URL + 'upp', 
            method: 'post',
            data: d                  
        }).then(function(res){
            x++;
            update_progress((x/queue_count)*100);
        });
    }
});

我想在 http 返回完成(200 OK)时调用 update_progress 函数,以便进度条正确显示实际进度。谢谢!

编辑

在调用 *update_progress* 函数之前,我尝试检查响应状态,但它仍然无法按预期工作。我不知道在请求完成之前发送了 200 :|按逻辑,res obj 不应该是 http 请求的 response 吗?我的意思是,如果它是 200 而不是错误代码,那不应该意味着请求已完成?

angular.forEach(queue, function (item) {
if (item.uid) {
    d.item = item;
    $http({
        url: BASE_URL + 'upp', 
        method: 'post',
        data: d                  
    }).then(function(res){
        if(res.status == 200) {
          x++;
          update_progress((x/queue_count)*100);
        }
    });
}

阅读更多关于 promises atm 的内容,看看我是否可以按照@josh-strange 的说法让它工作

编辑 2

因此,promise 是这样做的方式,所有请求都是按顺序发送的,因此进度条按预期工作,代码如下:

var promise = $q.all({}); 
// Had to init $q.all with an empty obj, 'cause null was trowing errors

angular.forEach(queue, function(item){
  if (item.uid) {        
    promise = promise.then(function(){
      d.item = item;
      return $http({
        url: BASE_URL + 'upp', 
        method: 'post',
        data: d 
      }).then(function(res){
        x++;
        update_progress((x/queue_count)*100);
      });
    });
  }
});

promise.then(function(){
  end_js_update();
});

谢谢@josh-strange

【问题讨论】:

  • 不要使用forEach,手动遍历队列?也不确定这是否可行。异步有时会很痛苦。
  • cannot 在 AngularJS 中进行同步调用,但您可以进行顺序 http 调用(Reg 1,然后是 Reg 2,等等)。让我试着为你准备一个 Plunker。
  • Here 是一个非常简单的顺序 HTTP 请求示例,我会在一分钟内发布一个答案并对其进行清理。
  • @AntonioMax 下面我的回答能解决你的问题吗?
  • @josh-strange 试图在我的代码上实现逻辑。如果按预期工作,将更新并接受。以前从未创建过承诺,所以我正在阅读文档。

标签: twitter-bootstrap angularjs


【解决方案1】:

这是一个有效的Plunker 连续 http 请求的工作示例。您显然可以将它很好地打包到服务中,但出于您的目的,我只是在控制器中放置了一个简单的示例。

这是代码的“肉”:

var app = angular.module('testApp',[]);

app.controller('myController', function($scope, $http, $q){

  $scope.responses = [];
  $scope.doneLoading = false;
  var urls = [
    'http://httpbin.org/ip',
    'http://httpbin.org/user-agent',
    'http://httpbin.org/headers'
  ];

  var promise = $q.all(null);

  angular.forEach(urls, function(url){
    promise = promise.then(function(){
      return $http({
        method: 'GET', 
        url:url 
      }).then(function(res){
        $scope.responses.push(res.data);
      });
    });
  });

  promise.then(function(){
    //This is run after all of your HTTP requests are done
    $scope.doneLoading = true;
  })

});

编辑:正如 Mike P 所说:这是链接承诺的示例,请参阅$q documentation

【讨论】:

  • 为了完整起见,这是一个将 Promise 链接在一起的示例(参见 $q 文档 @docs.angularjs.org/api/ng.$q)。
  • 感谢您添加 Mike,我会将其添加到答案中!
  • 感谢您的出色解决方案,它很漂亮!
【解决方案2】:

你可以试试这样的。等上一个请求完成后再发送下一个请求?

var sendRequest = function(index) {
  if (queue[index].uid) {
    d.item = queue[index];
    $http({
      url: BASE_URL + 'upp', 
      method: 'post',
      data: d                  
    }).then(function(res){
      if (index != queue.length - 1) {
        x++;
        update_progress((x / queue_count) * 100);
        sendRequest(++index);
      }
    });
  }
}

【讨论】:

  • 谢谢,但@josh-strange 的回答更好,因为它使用了 Promise,我相信现在这是正确的做法!
猜你喜欢
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多