2017-02-16 24 views
0

アイテムがある場合はリストをループし、各アイテムの場合は外部APIをajaxコールします。ajaxループが途切れる

これはループでも個別にも呼び出すことができます。しかし、私がしたいのは、ユーザーにいつでもリクエストをキャンセルするオプションを与えることです。リストが小さい場合(約< 20)、プロセスは約2〜3秒で完了します。これは問題ありません。しかし、時にはリストが数百になることもあり、実行には数分かかることがあり、いつでもキャンセルするオプションをユーザに与えたいことがあります。

これは私が現時点で持っているものです。

<button type="button" class="btn btn-default" ng-click="getData(myList)">Get All Data</button> 
<button type="button" class="btn btn-default" ng-click="cancelProcessCalls()">Get All Data</button> 

<div ng-repeat="item in myList"> 
    <div> 
     <div>{{item.Id}}</div> 
     <div>{{item.Name}}</div> 
     <div> 
      <span ng-bind-html="item.statusText"></span> 
      <span ng-bind="item.Data"></span> 
     </div> 
    </div> 
</div> 

角度/ jqueryのコードは次のとおりです。

$scope.getData = function (itemList) { 
    if (itemList != null) { 
     $.each(itemList, function (index, item) { 
      $scope.getItemData(item); 
     }); 
    } 
}; 

$scope.cancelProcessCalls = function() { 
    $scope.processCalls=false; 
}; 

$scope.getItemData = function (item) { 
    if ($scope.processCalls) { 
     if (item != null) { 
      item.statusText = "Getting data..."; 

      $.ajax({ 
       url: _url + item.Id, 
       method: 'GET' 
      }) 
      .fail(function (data, textStatus, jqXHR) { 
       $scope.handleError(data, textStatus, jqXHR); 
      }) 
      .done(function (data) { 
       item.Data = data; 
      }) 
      .then(function (data, textStatus, jqXHR) { 
      }) 
      .always(function (data, textStatus, jqXHR) { 
       item.statusText = null; 
       $scope.$apply(); 
      }); 
     } 
    } 
}; 

だから、最初の関数はリストだけをループし、各項目の呼び出しを行います。

私は、呼び出しを続行するかどうかをチェックする変数に追加しようとしましたが、すべてが作業範囲にラップされているため機能しません。

ループをエレガントにキャンセルまたは解除する簡単な方法はありますか?

+1

最初に複数のajaxコールを実行しますか? – madalinivascu

+0

すべてのajaxリクエストを配列の中に格納します。キャンセルがループしたときに呼び出され、[abort](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort)メソッドが呼び出されます。それらは – George

+0

@ madalinivascu - ループする複数のレコードがあるためです。私はバックエンドプロセスにリストを渡してそのループを通過させることができますが、現在のところ、既存のプロセスはキャンセル能力なしで完全に正常に動作します。私はプロセス全体を再設計するつもりはなく、すぐに修正があると思っていました。 – DeclanMcD

答えて

1

何かこれはうまくいくはずです。考え方は、xhrオブジェクトを配列に格納してから、キャンセルしたいときに配列の周りをループし、要求に対してアボートを呼び出すことです。

$scope.requests = []; 

    $scope.getData = function(itemList) { 
    $scope.cancelProcessCalls(); 
    if (itemList != null) { 
     $.each(itemList, function(index, item) { 
     $scope.getItemData(item); 
     }); 
    } 
    }; 

    $scope.cancelProcessCalls = function() { 
    for (var i = 0; i < $scope.requests.length; i++) { 
     $scope.requests[i].abort(); 
    } 

    $scope.requests.length = 0; 
    }; 

    $scope.getItemData = function(item) { 
    if ($scope.processCalls) { 
     if (item != null) { 
     item.statusText = "Getting data..."; 

     var xhr = $.ajax({ 
      url: _url + item.Id, 
      method: 'GET' 
     }); 
     $scope.requests.push(xhr); 

     xhr.fail(function(data, textStatus, jqXHR) { 
      $scope.handleError(data, textStatus, jqXHR); 
      }) 
      .done(function(data) { 
      item.Data = data; 
      }) 
      .then(function(data, textStatus, jqXHR) {}) 
      .always(function(data, textStatus, jqXHR) { 
      item.statusText = null; 
      $scope.$apply(); 
      });); 
    } 
    } 
+0

次のエラーが表示されます。 オブジェクトがプロパティまたはメソッド 'abort'をサポートしていません $ scope.requests [i] .abort(); – DeclanMcD

+1

答えで自分のコードを更新しようとしていますが、この[JSFiddle](http://jsfiddle.net/rvtx1sb7/1/)で作業コード – George

+0

を確認してください。私は問題を再現するためのフィドルを作成する方法を考え出すことさえできませんでした! – DeclanMcD

0
$scope.breakCheck = false; 
$scope.getData = function (itemList) { 
    if (itemList != null) { 
     $.each(itemList, function (index, item) { 
      if ($scope.breakCheck) { 
       return; 
      } 
      $scope.getItemData(item, $scope); 
     }); 
    } 
}; 

$scope.cancelProcessCalls = function() { 
    $scope.processCalls=false; 
}; 

$scope.getItemData = function (item, scope) { 
    scope.breakCheck = true; // You can move this line anywhere to decide when you want to stop the ajax 
    if ($scope.processCalls) { 
     if (item != null) { 
      item.statusText = "Getting data..."; 

      $.ajax({ 
       url: _url + item.Id, 
       method: 'GET' 
      }) 
      .fail(function (data, textStatus, jqXHR) { 
       $scope.handleError(data, textStatus, jqXHR); 
      }) 
      .done(function (data) { 
       item.Data = data; 
      }) 
      .then(function (data, textStatus, jqXHR) { 
      }) 
      .always(function (data, textStatus, jqXHR) { 
       item.statusText = null; 
       $scope.$apply(); 
      }); 
     } 
    } 
}; 
+0

あなたはまさに同じことをしているprocessCallsと呼ばれる場所に、すでにbreakCheckという変数を追加しています。 – DeclanMcD

+0

動作しますか?そうであれば、それを掃除することができます。そうでない場合は、エラー/何が間違っているのを投稿してください。 – Bwaxxlo

+0

いいえ、それは私が現時点で持っているのと全く同じです。私は、breakCheck変数をcancelProcessCallsメソッドに移動しましたが、それでもループします。残念ながら、最終的に変数値を更新するだけです。 – DeclanMcD

関連する問題