我有一个带有一些div的jQuery集合。对于每个div,我必须做两个ajax调用,而第一个调用返回一个被第二个调用使用的id。所有ajax调用都需要一些时间(让我们说一秒钟)。
如果我这样做:
$divs.each(function(index, element) {
$.get('/some/url').done(function (id) {
$.post('/some/other/url?id=' + id).done(function() {
$(element).doSomething();
});
})
});
然后所有获取调用将首先完成,然后所有发布调用。这没有错,但是,我希望尽早执行 post 调用,以便更快地向用户显示第一个结果。
所以我不想要:
get, get, get, get, get, get, get, get, post, post, post, post, post, post, ...
而不是这个:
get, get, get, get, get, post, get, post, get, post, get, post, get, post, ...
换句话说:只要第一次调用div,就立即开始第二次调用。不要等到所有第一次通话完成。
我想我必须以某种方式排队。我一定要吗?或者我怎么能实现这个目标?
注意:浏览器并行执行有限数量的ajax调用。默认情况下,Firefox中的AFAIK 6(Connections per Hostname)。 $.get()
调用可能很快,但连接限制会导致提取可能需要一些时间。 6队排队有帮助吗?或者我应该为每个div设一个队列吗?
额外的任务是取消整个处理,如果可能的话。
更新/解决方案:人们并不了解我的问题所在。正如一些人建议我现在使用priorityQueue in async库。有了这个,我可以减少挂起连接的数量并控制请求的顺序。
答案 0 :(得分:0)
嗨,看看这种方法是否可以帮到你:
var divs = $("div");
recursiveFunction(divs);
function recursiveFunction(divs){
var element = divs.shift();
$.get('/some/url').done(function (id) {
$.post('/some/other/url?id=' + id).done(function() {
$(element).doSomething();
if(divs.length > 0){
recursiveFunction(divs);
}
});
})
}
这样你就可以获得,发布,获取,发布。
答案 1 :(得分:0)
我认为您的代码没有任何问题。只是你不能注意到触发事件。
要更好地控制异步调用,您可以使用https://caolan.github.io/async/docs.html#controlflow
让我们说你的每个ajax(get和post)调用需要1秒,并且循环中每个项目的处理需要几毫秒,比如说10ms。所以对于5个div:
10ms 1st div
-> get sent
20ms 2nd div
-> get sent
30ms 3rd div
-> get sent
40ms 4th div
-> get sent
50ms 5th div
-> get sent
(总共50毫秒)所有ajax排队,但第一个div的获取仍在处理中,并将在1010ms
上回复,之后将发送请求
现在随着时间的推移,将会发生以下事件
(all get requests sent)
1010ms 1st div
-> post sent
1020ms 2nd div
-> post sent
1030ms 3rd div
-> post sent
1040ms 4th div
-> post sent
1050ms 5th div
-> post sent
所以从上面的顺序是
get1, get2, get3, get4, get5, post1, post2, post3, post4, post5
没有错。
答案 2 :(得分:0)
你的代码很好。您看到延迟的原因是因为您的所有获取都被抛入Javascript队列。有效地执行第一次获取然后排队您的帖子请求,但是,您的帖子前面还有其他信息。
正如其他人所指出的,网络延迟和服务器端处理get / post请求的时间会加剧这种情况。从用户体验中改善延迟问题的唯一真正解决方案是对请求进行分块。基本上,排队x获取请求,比如4,然后在完成请求后加载x更多get请求或使用settimeout并猜测延迟或通过事件触发后续请求。在我看来,后两者是不能很好地扩展的黑客。我建议使用第一个选项并下载async js库并使用parallel()方法对前四个进行排队,并使用可选的回调来启动下一个批处理。冲洗并重复。
答案 3 :(得分:-1)
$.get()
方法异步返回。
这意味着你是正确的,所有$.get()
将按顺序执行,同步,然而每个回调函数(.done()
s内的回调函数)将异步调用。
调用回调所花费的时间可能会有所不同,而$.get()
执行的时间几乎为0,所以你现在这样做的方式很好。