我需要做一系列N ajax请求,而不锁定浏览器,并希望使用jquery deferred对象来完成这个。
这里是一个简单的例子,有三个请求,但我的程序可能需要排队超过100(注意,这不是确切的用例,实际代码确实需要确保步骤(N-1)成功执行下一个步):
@H_403_4@$(document).ready(function(){ var deferred = $.Deferred(); var countries = ["US","CA","MX"]; $.each(countries,function(index,country){ deferred.pipe(getData(country)); }); }); function getData(country){ var data = { "country": country }; console.log("Making request for [" + country + "]"); return $.ajax({ type: "POST",url: "ajax.jsp",data: data,dataType: "JSON",success: function(){ console.log("Successful request for [" + country + "]"); } }); }这里是写入控制台(所有请求并行进行,响应时间直接与每个国家的数据大小成正比的预期:
@H_403_4@Making request for [US] Making request for [CA] Making request for [MX] Successful request for [MX] Successful request for [CA] Successful request for [US]如何获得延迟对象排队这些为我?我试过更改完成管,但得到相同的结果。
这里是所需的结果:
@H_403_4@Making request for [US] Successful request for [US] Making request for [CA] Successful request for [CA] Making request for [MX] Successful request for [MX]编辑:
我赞赏使用数组来存储请求参数的建议,但是jquery deferred对象有排队请求的能力,我真的想学习如何使用这个功能的全部潜力。
这实际上是我想做的:
@H_403_4@when(request[0]).pipe(request[1]).pipe(request[2])... pipe(request[N]);但是,我想要将请求分配到管道中,一次一步,以有效地使用每个遍历:
@H_403_4@deferred.pipe(request[0]); deferred.pipe(request[1]); deferred.pipe(request[2]);解决方法
使用自定义对象
@H_403_4@function DeferredAjax(opts) {
this.options=opts;
this.deferred=$.Deferred();
this.country=opts.country;
}
DeferredAjax.prototype.invoke=function() {
var self=this,data={country:self.country};
console.log("Making request for [" + self.country + "]");
return $.ajax({
type: "GET",url: "wait.PHP",success: function(){
console.log("Successful request for [" + self.country + "]");
self.deferred.resolve();
}
});
};
DeferredAjax.prototype.promise=function() {
return this.deferred.promise();
};
var countries = ["US","MX"],startingpoint = $.Deferred();
startingpoint.resolve();
$.each(countries,function(ix,country) {
var da = new DeferredAjax({
country: country
});
$.when(startingpoint ).then(function() {
da.invoke();
});
startingpoint= da;
});
小提琴http://jsfiddle.net/7kuX9/1/
为了更清楚,最后一行可以写
@H_403_4@c1=new DeferredAjax( {country:"US"} ); c2=new DeferredAjax( {country:"CA"} ); c3=new DeferredAjax( {country:"MX"} ); $.when( c1 ).then( function() {c2.invoke();} ); $.when( c2 ).then( function() {c3.invoke();} );管道
@H_403_4@function fireRequest(country) { return $.ajax({ type: "GET",data: {country:country},success: function(){ console.log("Successful request for [" + country + "]"); } }); } var countries=["US",startingpoint=$.Deferred(); startingpoint.resolve(); $.each(countries,country) { startingpoint=startingpoint.pipe( function() { console.log("Making request for [" + country + "]"); return fireRequest(country); }); });编辑:在结果窗口http://jsfiddle.net/k8aUj/3/中输出日志的小提琴
每个管道调用返回一个新的promise,它又用于下一个管道。注意,我只提供sccess功能,应该提供类似的功能失败。
在每个解决方案中,Ajax调用被延迟,直到需要通过将它们包装在一个函数中,并为列表中的每个项目创建一个新的promise来构建链。
我相信自定义对象提供了一个更容易的方式来操纵链,但管道可以更好地适合你的口味。
注意:作为jQuery 1.8,deferred.pipe()
已弃用,deferred.then
替换它。