进行两系列异步调用,中间延迟

时间:2015-08-23 15:25:03

标签: javascript ajax asynchronous

我需要进行一系列AJAX调用(到不同的URL),然后只有在完成所有之后才进行另一系列调用。到目前为止我的代码:

(function (delay) {
    var toDo = 10, // for example
    curr = 0;
    process = setInterval(function() {
        // do a call
        // blahblahblah
        // then:
        if(curr === toDo) {
            clearInterval(process);
        } else {
            curr++;
        }
    }, delay);
})(2000);
// repeat for the 2nd series, but this code will execute immediately since they are async

我使用此格式而不是简单for循环的原因是因为我需要在每次调用之间暂停。直到完成第一个系列之后我才能启动第二个系列,因为我从那里获得了第二个系列的URL;所以我不能把所有的电话都推到同一个自我调用函数中。第一个系列完成后,我需要第二个系列才能执行

4 个答案:

答案 0 :(得分:2)

假设jQuery,你应该能够使用promises:

$.when( // first set
    $.ajax({}),
    $.ajax({})
).then(function(){ // second set
    $.ajax({});
    $.ajax({});
});

答案 1 :(得分:1)

  

我使用这种格式而不是简单的for循环的原因是   因为我需要在每次通话之间暂停。我无法推出第二名   系列直到第一个系列全部完成后,自那以后   我从第二个系列中获取了URL;所以我不能把所有的东西推开   调用相同的自调用函数。我需要第二个系列   仅在第一个系列完成后执行。

返回预期结果似乎没有必要延迟?尝试使用var requests = [function doAsyncStuff1() {}, function doAsyncStuff2() {}]; var res = Promise.all(requests.map(function(request) { return request() })); res.then(function success(data) { // do stuff with response from `doAsyncStuff1` , `doAsyncStuff2` }, function error(err) { // log errors , if any console.log(err) });

    ciphers:[       "ECDHE-RSA-AES256-SHA384",
                    "DHE-RSA-AES256-SHA384",
                    "ECDHE-RSA-AES256-SHA256",
                    "DHE-RSA-AES256-SHA256",
                    "ECDHE-RSA-AES128-SHA256",
                    "DHE-RSA-AES128-SHA256",
                    "HIGH",
                    "!aNULL",
                    "!eNULL",
                    "!EXPORT",
                    "!DES",
                    "!RC4",
                    "!MD5",
                    "!PSK",
                    "!SRP",
                    "!CAMELLIA"
            ].join(':'),
    honorCipherOrder: true

答案 2 :(得分:1)

我将假设您的第二个系列的代码都已设置并且易于使用,您需要帮助的是确保第二个系列仅在第一个系列完成后调用。有了这个假设,这里有一些伪代码,你需要做什么:

(function (delay) {
    var toDo = 10, // for example
    curr = 0,
    numDone = 0; //This is the number of requests we've finished and gotten a response for.
    process = setInterval(function() {
        // Setup a call.
        [...]
        // Make some callback that _at the end, increments numDone_.
        [...]
        // Send the call.
        [...]
        // Then:
        if(curr === toDo) {
            clearInterval(process);

            //Now, here's where we check if we're done with all of these requests:
            (function(delay2) {
                 //Every so often, check if we're done by seeing if numDone equals toDo:
                 var checkDone = setInterval(function() {
                     if (numDone === toDo) {
                         //Thus, stop checking if we're done:
                         clearInterval(checkDone);
                         //Finally, start the second series of calls:
                         [...]
                     }
                 }, delay2);
            })(1000);
            //We're checking every second as passed in above, but you can change this however you want.
        } else {
            curr++;
        }
    }, delay);
})(2000);

答案 3 :(得分:1)

$ http方法返回一个promise。您可以使用then回调来调用下一个ajax请求。这使用$q服务,这是有角度的承诺服务,因此请务必将其注入您的控制器/工厂/指令。



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

app.controller("MainCtrl",["$scope","$q","$http",function($scope,$q,$http){
  $scope.log = [];

  //Start the requests for the next set of urls
  function nextSet(urls){
     var deferreds = urls.map(function(url){
         $scope.log.push("Starting url: "+url);
         return $http.get(url);
     });

     //$q.all takes an array of deferreds and will be fulfilled when 
     //all of them resolve.
     return $q.all(deferreds);
  }

  var urlSets = [ 
     [ "https://cors-test.appspot.com/test?1",
       "https://cors-test.appspot.com/test?2" ], 
     [ "https://cors-test.appspot.com/test?3",
       "https://cors-test.appspot.com/test?4",
       "https://cors-test.appspot.com/test?5"] ];
  var dataSets = [];
    
  //The main deferred
  var deferred = $q.defer();

  //Loop through the sets, chaining 'then'
  //This will end up basically making up a queue
  //Each chained 'then' callback will be called after
  //each set of requests have resolved
  var promise = urlSets.reduce(function(promise,urlSet){

     //return promise so it can be used in the next iteration
     return promise
       
       //Chain the nextSet call, binding the urlSet to the call
       .then(nextSet.bind(null,urlSet))
       
       //Just chaining an extra callback to show previous call was done
       //Could use it to do special processing for each set
       //after they have been fetched
       .then(function(dataSet){
         $scope.log.push("Set Finished: "+urlSet.join(","));
         dataSets.push(dataSet);
         return dataSets;
       });

  },deferred.promise);

  //The final 'then' callback, called when all sets have been resolved
  promise.then(function(dataSets){
    //All done
    $scope.log.push("All done");
    
    //all the data fetched from urls will be in dataSets
    //it will be an array of the sets with each index matching to 
    //to the indexes of the urlSets. so dataSets[0] will hold the array of             
    //data fetched from urlSets[0] and so on
    console.log(dataSets);
  });
  
  //Start the process
  deferred.resolve();      
}]);

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MainCtrl">
  <ul>
    <li ng-repeat="line in log">
      {{line}}
    </li>
   </ul>
</div>
&#13;
&#13;
&#13;

此代码假定所有网址都将解析。如果任何请求失败,则不会处理其余请求。如果您需要处理剩余的请求,即使其中任何一个请求失败,您还需要添加适当的代码来处理这种情况。

Angular's $q service