我正在使用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站点数据。如何确定最后一次异步调用何时完成?
答案 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
});
小提示:
答案 1 :(得分:1)
不幸的是答案是我使用了错误的语法。
我改变了:
$.when.apply($, promises).then(processFinalTable());
为:
$.when.apply($, promises).then(processFinalTable);
现在一切正常。