2017-02-16 158 views
0

我有一个函数,如果项目,然后为每个项目,它会使ajax调用外部api,通过列表循环。突破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请求存储在数组中,当调用cancel时,循环它们并调用[abort](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort)方法他们 – George

+0

@madalinivascu - 因为有多个记录循环。我可以将一个列表传递给后端进程,并通过这个循环,但是现在,现有的进程完全正常工作,没有取消功能。我不打算重新设计整个过程,只是认为有一个快速解决方案。 – DeclanMcD

回答

1

像这样的东西应该工作。这个想法是,你将xhr对象存储在一个数组中,然后当你想取消你循环的数组并在请求中调用abort。

$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

我收到以下错误: 对象不支持属性或方法'中止' 当它到达行 $ 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

你刚刚添加了一个名为breakCheck的变量,我已经在那里调用了processCalls,它完成了同样的事情吗? – DeclanMcD

+0

它工作吗?如果是这样,你可以考虑清理它。如果没有,请发布错误/出错 – Bwaxxlo

+0

不,这与我目前的完全一样。我将breakCheck变量移入了cancelProcessCalls方法,但仍然循环。它只更新最后的变量值,不幸的是 – DeclanMcD