javascript 在循环中使用 $.Deferred() 和嵌套的 ajax 调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13951456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using $.Deferred() with nested ajax calls in a loop
提问by jokkedk
I've spent far too many hours searching for similar questions and trying solutions, so I hope someone has a solution.
我花了太多时间寻找类似的问题并尝试解决方案,所以我希望有人有解决方案。
Basically, I would like to be notified when a function a() has completed. The problem is that the function contains an ajax call and a loop that calls b(), which again contains an ajax call.
基本上,我希望在函数 a() 完成时收到通知。问题在于该函数包含一个 ajax 调用和一个调用 b() 的循环,而 b() 又包含一个 ajax 调用。
UPDATED WITH FIDDLE: http://jsfiddle.net/hsyj7/1/
用小提琴更新:http: //jsfiddle.net/hsyj7/1/
Like so:
像这样:
// called by main()
function a() {
return $.ajax("http://url1").pipe(function(data){
for (var i = 0; i < 2; i++) {
console.log('a called');
b();
}
});
}
// called by a()
function b() {
for (var i = 0; i < 2; i++) {
$.ajax("http://url2", function(data){
// do something
console.log('b called');
}
}
}
function main(){
$.when(a()).done(function(){
console.log('all completed');
});
}
What I would like to see then is, possibly with both calls to a() at the top:
我想看到的是,可能在顶部同时调用 a() :
a called
b called
b called
a called
b called
b called
all completed
Instead I get
相反,我得到
a called
all completed
b called
b called
Or some variant thereof.
或者它的一些变体。
I am aware that the above code is missing defer functionality in both the loop and in b(). In some of the variants I have tried, the done() handler in main() is never called.
我知道上面的代码在循环和 b() 中都缺少延迟功能。在我尝试过的一些变体中,从未调用过 main() 中的 done() 处理程序。
Any one know how to do this?
有人知道怎么做吗?
采纳答案by freakish
Yeah, using Deferred
is the way to do that:
是的,使用Deferred
是这样做的方法:
function a() {
var def = $.Deferred();
$.ajax("http://url1").done(function(data){
var requests = [];
for (var i = 0; i < 2; i++) {
requests.push(b());
}
$.when.apply($, requests).then(function() { def.resolve(); });
});
return def.promise();
}
// called by a()
function b() {
var def = $.Deferred(),
requests = [];
for (var i = 0; i < 2; i++) {
requests.push($.ajax("http://url2").done(function(data){
// do something
console.log('b called');
});
}
$.when.apply($, requests).then(function() { def.resolve(); });
return def.promise();
}
function main(){
$.when(a()).done(function(){
console.log('all completed');
});
}
//EDIT: Replaced .pipe
with .done
.
//编辑:替换.pipe
为.done
.
回答by jAndy
You could use an Arraywhich is located in a higher context to push Promise / Deferredobjects into. Then you could then use jQuery.when
alongside Function.prototype.apply
to pass all entries as arguments.
您可以使用位于更高上下文中的Array将Promise / Deferred对象推入。然后,您可以使用jQuery.when
withFunction.prototype.apply
将所有条目作为参数传递。
(function() {
var promises = [ ],
when = Function.prototype.apply.bind( jQuery.when, null );
function a() {
promises.push($.ajax("http://url1").pipe(function(data){
for (var i = 0; i < 2; i++) {
console.log('a called');
b();
}
}));
return promises;
}
function b() {
for (var i = 0; i < 2; i++) {
promises.push($.ajax("http://url2", function(data) {
// do something
console.log('b called');
}));
}
}
function main() {
promises = [ ];
when( a() ).done(function(){
console.log('all completed');
});
}
}());
回答by Bergi
The question might be old, but since there's no correct solution yet I'll put an answer here. It properly chains the promises by using .then
(previsouly been .pipe
) to achieve the requested result:
这个问题可能很老,但由于还没有正确的解决方案,我会在这里给出答案。它通过使用.then
(previsouly been .pipe
)正确链接 promises来实现请求的结果:
function a() {
return $.ajax("http://url1").done(function(data){
console.log('a called');
}).then(function(){
return $.when(b(), b()); // no loop for simplicity
});
}
function b() {
return $.ajax("http://url2").done(function(data){
console.log('b called');
});
}
function main(){
a().done(function(){
console.log('all completed');
}, function() {
console.log('an error occured!');
});
}
Depending on which result data should be available where the nesting/structure might be changed, but the overall ordering is correct.
根据哪些结果数据应该可用,嵌套/结构可能会更改,但整体排序是正确的。
回答by Jamie Hutber
I believe this can be fixed with callbacks, but a fiddle would have really helped me check for you.
我相信这可以通过回调来解决,但是小提琴真的可以帮助我检查你。
// called by main()
function a(callback) {
//set this to the number of loops that is going to happen
var number = 2;
return $.ajax("http://url1", function(data){
console.log('a called');
for (var i = 0; i < number ; i++) {
b();
if(number===i){
callback();
}
}
}
}
function main(){
a(function(){
//Function or code you want to run on completion..
});
}
Forgive me if this doesn't work, but i think its the right direction.
如果这不起作用,请原谅我,但我认为这是正确的方向。