Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
326 views
in Technique[技术] by (71.8m points)

javascript - Using $.Deferred() with nested ajax calls in a loop

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.

UPDATED WITH FIDDLE: 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 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.

Any one know how to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yeah, using Deferred is the way to do that:

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...