如何等待大量,任意数量的深度嵌套的异步jQuery ajax调用来完成

时间:2014-08-12 03:27:41

标签: jquery ajax asynchronous sharepoint-2013

我正在使用SharePoint休息网络服务界面从网站获取大量数据。

这涉及对不同服务的深度嵌套ajax调用(即获取网站,获取它的列表,获取所有列表的项目,每个项目,获取它的属性,获取webhsite的子站点...重复)。

我正在使用一组promises,将每个调用推送到数组中:

 promises.push($.ajax({
        url: fullurl,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {                  
                  $.each(data.d.results, function(i, item) {
                ProcessData(i,item, tableTarget, columns, promises);                                                
                   });      
        },
        error: function (data) {
                console.log("request failed: " + fullurl);
        }
    }));

每次调用ProcessData都可能会在html表('tableTarget')中添加一行,并调用更多数据。

理想情况下,我想延迟尝试过滤表的脚本,直到所有数据都存在。 问题是当我打电话给

var promises = [];
//kickoff my data gathering
AddWebData(url,tableTarget, promises);
//apply
$.when.apply($, promises).then(processFinalTable(promises));    

promises数组中只有大约2个项目,因此processFinalTable调用过早。 如果我延迟

的setTimeout(函数(){     console.log('等待4000');     $ .when.apply($,promises).then(processFinalTable(promises));
},4000);

承诺清单有400个左右的项目。总的来说,我实际上需要等待1200多个ajax调用(不要问)。

鉴于我要进行任意数量的调用,具体取决于SharePoint站点数据。如何确定最后一次异步调用何时完成?

2 个答案:

答案 0 :(得分:1)

这样的事情怎么样?将您的调用封装在一个函数中,该函数返回一个延迟对象,该对象在您的所有调用完成后得到解决。代码被评论以帮助澄清正在发生的事情:

MIN_DELAY = 200;
MAX_DELAY = 2000;

function mockAjaxCall() {
  var deferred = jQuery.Deferred();
  var ms_delay = Math.floor(Math.random() * (MAX_DELAY - MIN_DELAY + 1)) + MIN_DELAY;

  setTimeout(function() {
    deferred.resolve(ms_delay);
  }, ms_delay);

  return deferred;
}

function collectAllThatData() {
  var allCallsComplete = jQuery.Deferred();
  var callsPending = [];
  var callsComplete = [];
  var ms_interval = 250;

  // Let's mock 40 asynchronous AJAX calls with random delays
  for (var i=0; i<40; i++) {
    var promise = mockAjaxCall();
    callsPending.push(promise);
  }

  // As promises are resolved, add to callsComplete array.
  jQuery.each(callsPending, function(n, callPending) {
    jQuery.when(callPending).done(function() {
      callsComplete.push(callPending);
    });
  });

  // At defined interval, compare callsComplete to callsPending to determine
  // if all our calls are complete.
  var intervalId = setInterval(function() {
    console.log(callsComplete.length, 'calls complete');

    if ( callsComplete.length >= callsPending.length ) {
      clearInterval(intervalId);
      allCallsComplete.resolve(callsComplete);
    }
  }, ms_interval);

  // Return a deferred object for calling script to use.
  return allCallsComplete;
}

var allThatDataCollected = collectAllThatData();

jQuery.when(allThatDataCollected).then(function() {
  console.log('Data has been collected!');
  // Do something else
});

小提示:

http://jsfiddle.net/klenwell/jyza3050/

答案 1 :(得分:1)

不幸的是答案是我使用了错误的语法。

我改变了:

$.when.apply($, promises).then(processFinalTable());    

为:

$.when.apply($, promises).then(processFinalTable);    

现在一切正常。