31

私は似たような質問を探して解決策を試すのに非常に多くの時間を費やしてきたので、誰かが解決策を持っていることを願っています。

基本的に、関数a()が完了したときに通知を受け取りたいと思います。問題は、関数にajax呼び出しと、b()を呼び出すループが含まれていることです。このループにもajax呼び出しが含まれています。

FIDDLEで更新:http://jsfiddle.net/hsyj7/1/

そのようです:

// 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');
  });
}

私が見たいのは、おそらく上部にa()を両方呼び出した場合です。

a called
b called
b called
a called
b called
b called
all completed

代わりに私は得る

a called
all completed
b called
b called

またはそのいくつかの変形。

上記のコードには、ループとb()の両方で遅延機能が欠落していることを認識しています。私が試したいくつかのバリアントでは、main()のdone()ハンドラーが呼び出されることはありません。

誰かがこれを行う方法を知っていますか?

4

4 に答える 4

30

ええ、使用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');
    });
}

//編集:。に置き換えられまし.pipe.done

于 2012-12-19T11:43:38.480 に答える
2

より高いコンテキストにある配列を使用して、Promise/Deferredオブジェクトをにプッシュできます。次に、jQuery.when一緒Function.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');
        });
    }
}());
于 2012-12-19T11:49:55.610 に答える
2

質問は古いかもしれませんが、正しい解決策がまだないので、ここに答えを入れます。要求された結果を達成するために.then(以前は)を使用して、約束を適切に連鎖させます。.pipe

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!');
  });
}

ネスト/構造が変更される可能性のある場所で利用できる結果データによって異なりますが、全体的な順序は正しいです。

于 2014-02-13T08:43:26.950 に答える
1

これはコールバックで修正できると思いますが、フィドルは私があなたをチェックするのに本当に役立ちました。

 // 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.. 
    });
 }

これがうまくいかない場合は許してください、しかし私はそれが正しい方向だと思います。

于 2012-12-19T11:40:20.207 に答える