3

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 要求の応答であってはなりませんか? つまり、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);
        }
    });
}

@josh-strange が述べたように、promise atm の詳細を読んで、動作させることができるかどうかを確認してください。

編集2

したがって、約束はそれを行う方法でした。すべてのリクエストは順番に送信されるため、進行状況バーは期待どおりに機能します。コードは次のとおりです。

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

4

2 に答える 2

13

これは、シーケンシャルな http リクエストの実際の例の実際のPlunkerです。もちろん、これをサービスにうまくパッケージ化することもできますが、目的のために、簡単な例をコントローラーに入れました。

コードの「要点」は次のとおりです。

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を参照してください。

于 2013-09-26T20:57:50.687 に答える
0

このようなことを試すことができます。前のリクエストが完了するまで、次のリクエストを送信するのを待ちますか?

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);
      }
    });
  }
}
于 2013-09-26T20:34:08.240 に答える