所以这是我的设置:我在一些元素上调用.each,经过几次检查后,我发送了一个带有一些JSON数据的ajax请求,并且在成功时我将服务器响应作为属性应用于每个元素(它通常是一个id)。之后我将id推送到数组。
问题是,显然ajax请求是异步的,并且在所有ajax有时间完成之前,使用元素id数组的函数会触发。
我已经尝试过.when和.then,但回调函数一直在ajax之前被激活。
以下是我的代码的外观(我删除了一些不必要的部分):
var order = [];
function sub(selector){
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
$.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
})
}
$("#button").click(function(){
$.when(sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
答案 0 :(得分:1)
问题是when
会对延迟对象起作用,但是子不会返回任何内容,因此when
会立即触发。所以你需要做的是收集ajax调用返回的所有延迟对象并返回它们:
var order = [];
function sub(selector){
var deferredList = []
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
var deferred = $.ajax({
type: "POST",
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
deferredList.push(deferred)
})
return deferredList;
}
$("#button").click(function(){
$.when.apply($,sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
直接使用apply
而非when
的原因是when
不接受对象数组作为参数,apply
为我们提供了工作 - 为了这个。
答案 1 :(得分:0)
$.when()
的参数应为Deferred
,但sub()
不返回任何内容。此版本返回Deferred
返回的所有$.ajax
的数组,并将$.when
作为参数调用;然后它将等待所有这些。
var order = [];
function sub(selector){
return selector.map(function(){
var out = {
"some":"random",
"stuff":"here"
};
return $.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
}
})
})
}
$("#button").click(function(){
$.when.apply(this, sub($(".test"))).then(function() {
console.log(order);
//i have to run the sub function twice so the order doesn't return undefined
});
});
答案 2 :(得分:0)
您的方法会产生更多的服务器请求,并且会非常严重。既然你想要等待所有结果,一个更好的解决方案是收集所有数据并只发送一个ajax请求,它返回每个数据对象的结果数组。
使用延迟对象(如其他答案中所示),然后您可以在when
语句中使用该结果。
答案 3 :(得分:0)
尝试成功使用回调函数:
var order = [];
function sub(selector, callback){
selector.each(function(){
var out = {
"some":"random",
"stuff":"here"
};
$.ajax({
type: "POST"
url: "/test/url",
dataType: 'json',
contentType: "application/json; charset=utf-8",
data:JSON.stringify(out),
success:function(response){
$(this).attr("data-response",response);
order.push(response);
callback();
}
})
})
}
$("#button").click(function(){
sub($(".test"), function() { console.log(order) });
});
答案 4 :(得分:-2)
将属性async:false添加到$ .ajax - call。然后在彼此之后按顺序进行调用。