如何匹配两个嵌套的ajax调用的结果?
一个例子:第一个调用获取一个url列表,并且每个调用的嵌套一个将检索页面的标题。会发生的是,当我进行第二次通话时,第一次通话会在后台继续,并且找不到我的结果。任何解决方案?
代码:
$.ajax({
dataType : "json",
url : queryUrlDoc,
success : function(json) {
queryResults = json.results.bindings;
var title;
var temp = [];
for(var i in queryResults){
var url = queryResults[i]['doc'].value;
$.ajax({
url: url,
type: 'get',
success: function(data) {
title = data;
var item = {
'url' : url,
'title': title
};
temp.push(item);
}
});
}
var titolo;
for(var i in temp) {
uri = temp[i]['url'];
titolo = temp[i]['title'];
//do stuff
}
},
error: function(){
alert("fail");
}
});
不幸的是,第二个'即使第一个人没有完成它的工作,周期也会开始......
答案 0 :(得分:3)
在处理之前,您是否需要等待所有ajax调用返回?如果没有,您可以执行以下操作:
$.ajax({
url: queryUrlDoc,
dataType: 'json',
success: function(json) {
$.each(json.results.bindings, function(i, queryResult) {
var url = queryResult.doc.value;
$.ajax({
type: 'get',
url: url,
dataType: 'text',
success: function(title) {
// Do stuff with url and title here.
}
});
});
},
error: function() {
alert('fail');
}
});
如果你确实需要等待所有人返回,它会变得有点复杂。您可以使用$.ajax()
returns a promise这一事实,然后在所有这些承诺得到解决后使用$.when()
执行代码。
$.ajax({
url: queryUrlDoc,
dataType: 'json',
success: function(json) {
var urls = [];
var promises = $.map(json.results.bindings, function(queryResult) {
var url = queryResult.doc.value;
urls.push();
return $.ajax({ type: 'get', url: url, dataType: 'text' });
});
$.when.apply($, promises).done(function() {
var titles = (promises.length > 1)
? $.map(arguments, function(a) { return a[0]; })
: [arguments[0]];
var items = $.map(urls, function(url, i) {
return { url: url, title: titles[i] };
});
// Do stuff with items array here.
}).fail(function() {
alert('fail');
});
},
error: function() {
alert("fail");
}
});
有关如何根据传递给titles
函数的回调的参数构造$.when(...).done()
数组的信息,请参阅this Stackoverflow answer。
上述代码的替代方法是使用$.Deferred()
为ajax调用创建自己的promise,以便控制已解析的数据。
$.ajax({
url: queryUrlDoc,
dataType: 'json',
success: function(json) {
var promises = $.map(json.results.bindings, function(queryResult) {
var url = queryResult.doc.value;
return $.Deferred(function(deferred) {
$.ajax({
type: 'get',
url: url,
dataType: 'text',
success: function(title) {
deferred.resolve({ url: url, title: title });
},
error: function(jqXHR, textStatus, errorThrown) {
deferred.reject([jqXHR, textStatus, errorThrown]);
}
});
}).promise();
});
$.when.apply($, promises).done(function() {
var items = $.makeArray(arguments);
// Do stuff with items array here.
}).fail(function() {
alert('fail');
});
},
error: function() {
alert('fail');
}
});
答案 1 :(得分:1)
这里有2个问题:设计和异步。
首先,为什么需要对第一个AJAX请求返回的每个元素进行AJAX调用?如果第一个请求发送100个元素,那么你将同时执行100个AJAX调用,并且只是杀死你的浏览器,这并不好。我认为您应该尝试减少完成的AJAX请求量,并且可能在第一个AJAX请求中检索所有必需的信息。你做的越少,它就越好(对于浏览器,对于用户,对服务器,对你来说也是如此)。
其次,你有异步问题。 AJAX调用是异步的。因此,在您当前的代码中,您在获取任何元素之前都使用temp
变量。看看这个,我已经简化了代码并添加了一些console.log
语句:
$.ajax({
dataType : "json",
url : queryUrlDoc,
success : function(json) {
console.log('First AJAX call is finished');
var queryResults = json.results.bindings;
var temp = [];
for(var i in queryResults)
{
var url = queryResults[i]['doc'].value;
$.ajax({
url: url,
type: 'get',
success: function(data) {
console.log('Second AJAX call is finished, with data: ' + data);
temp.push({
'url' : url,
'title': data
});
console.log('temp array now contains ' + temp.length + ' elements');
}
});
}
console.log('iterating over temp array, it contains ' + temp.length + ' elements');
for(var i in temp)
{
uri = temp[i]['url'];
}
}
});
你能猜出你会得到什么输出?我打赌你会得到这样的东西:
First AJAX call is finished
iterating over temp array, it contains 0 elements
Second AJAX call is finished, with data: <data from first subrequest>
temp array now contains 1 elements
Second AJAX call is finished, with data: <data from second subrequest>
temp array now contains 2 elements
看看发生了什么? for
循环在<{strong> {/ 1}}回调之前执行,因为AJAX调用是异步的。为了做你想做的事,你应该使用像Promises这样的东西(参见John的答案以获得更多解释)。
答案 2 :(得分:0)
尝试使用while
,类似的内容会在上一次成功之后发送下一个请求:
var next = false;
var i = 0;
while(next){
next = false;
var url = queryResults[i]['doc'].value;
$.ajax({
url: url,
type: 'get',
success: function(data) {
title = data;
var item = {
'url' : url,
'title': title
};
temp.push(item);
next=true;
i++;
}
});
}
希望这有帮助。
答案 3 :(得分:0)
在调用多个相关的AJAX调用时,你应该使用jQuery promises。
以下是一个例子:
var firstPromise = $.ajax("http://example.com/first");
var secondPromise = $.ajax("http://example.com/second");
$.when(firstPromise, secondPromise).done(function(firstData, secondData) {
// do something
});