2012-04-13 11 views
1

を解決されたとき、私は、次のコードを持って何かをします。言い換えれば、GetView ajax呼び出し、loadTypes関数、およびそれらのコールバックを含むloadOpportunities関数がすべて完了したときに、いくつかのコードを実行したいと思います。は、すべてのDeferredが

次のコールバック関数は、すべてが完了していない場合に発生します。これどうやってするの?

self.loadView.then(function() { 
    //Do something after ALL stuff, including all callbacks is done in loadView 
}); 
+0

各コールバックでイベントをトリガすることができます。このイベントは最終的な関数を呼び出しますが、3つのイベントがすべてトリガされたときにのみ関数を実行します。 – tkone

+0

私は 'deffered.resolve()'を返しません。 –

答えて

1

ここでは、延期、約束、パイプの使用について少し混乱することがあります。

var testObject = { 
    loadOpportunities: function() { 
    // This is basically saying that we're getting something via AJAX, but we want to take a swipe at changing it 
    // before anyone else gets it, so by using pipe we're returning a different promise than the AJAX promise and 
    // the value returned from that is what we want others to get. 
    return $.ajax({ 
     url: "/echo/json/", 
     data: opportunities, 
     type: "POST" 
     }).pipe(
     function (result) { 
      console.log("[1]", result); 

      // Change the result in some way and then return the changed result. Otherwise there's no point in using 
      // a pipe() here, a done() would work as well. 
      result.opportunities[0].name = "meat packer"; 

      return result; 
     } 
    );  
    }, 

    loadTypes: function() { 
    // This example is different from loadOpportunities in that it isn't using a pipe() so what is returned from 
    // this function is the same promise that $.ajax() gave us. Any call to .done() just echos back the same 
    // promise you gave it. 
    return $.ajax({ 
     url : "/echo/json/", 
     data : opportunityTypes, 
     type : "POST" 
     }).done(
     function (result) { 
      console.log("[1]", result); 

      // We can do something with the data received here, but outside of this function, anything that tied to 
      // the promise from the $.ajax() will see the original data, not any changes we might make here.      
     } 
    ); 
    }, 

    loadView: function() { 
    // The self = this, scope = this, etc. that you see at the start of functions is only necessary if there are 
    // closures below where this might be something else. This code doesn't have that so this line is unneeded. 
    // 
    // Be careful about cargo-cult programming and just doing something because you do it everywhere else or you 
    // see someone else do something. Try to understand why it's there. 
    // var self = this; 

    if (!this.viewLoaded) { 
     console.log("loading"); 
     var viewPromise = $.ajax({ 
      url : "/echo/json/", 
      data : view, 
      type : "POST" 
     }).done(
     function (result) { 
      console.log("[1]", result); 

      // We might take this and dump it in a <div> somewhere. 
     } 
    ); 

     var typesPromise = this.loadTypes(); 
     var opportunitiesPromise = this.loadOpportunities(); 

     // The following line hands back a single promise (that's what $.when() does) that wraps all three of the 
     // other promises and only fires when all three have completed OR when any one of them has failed. 
     return $.when(typesPromise, opportunitiesPromise, viewPromise).done(
     function() { 
      // Here I've tied a function to the promise as soon as I've created it. But since I'm handing back the 
      // promise, I can also tie functions to it later as well, even after the promise has resolved or been 
      // rejected. 
      console.log("[2]", "All done loading types, views, and opportunities"); 
     } 
    ); 
    } 

    return true; 
    } 
}; 

// Note: Unlike with all the steps labeled [1], I don't believe there is a formal ordering for the 
// .done()'s attached to the same promise like both [2] and [3]. So it may be possible for those two steps to 
// happen [2]/[3] or [3]/[2] although they always happened [2]/[3] in my testing. 
$.when(testObject.loadView()).done(
    function() { 
    console.log("[3]", "This will only trigger after all the steps in load view have completed."); 
    } 
); 

注:

は私が何をしたいことは、この(http://jsfiddle.net/JohnMunsch/ghdgD/)のようなものだと思う私はあなたのAJAX呼び出しのスタイルを変えたが、それは私がjsFiddleで実施例を構築するために必要なだけのためでした。上のリンクをクリックすると、そこのアクションが表示されます。それは動作し、期待どおりに物事を注文します。約束を守る人が結果を見る前に、AJAXの結果を操作するつもりでない限り、思ったほどパイプを必要としないでしょう。それ以外の場合は、.done()、.fail()、および.when()がほとんどの状況を処理します。

+0

バンドルありがとうございます。実際には混乱がありました。追加の質問:this.viewLoadedがloadView関数でtrueの場合、動作しません。どのように解決するのですか? – RolandG

+0

実際には、私のコードはそれを問題なく処理します。そして、なぜここに... $ .when()がスマートなので、約束またはそれらのセットを渡すと、すべてに結びついている約束が返されます。ただし、約束していないものを手渡した場合、すぐに新しいDeferredオブジェクトが作成され、promise_の代わりに得られた値を使用して解決されます。したがって、testObject.loadView()を呼び出すと、単に "true"が返されると、$ .when()はただちに完了し、[3]が実行されます。 loadView()の上部に "this.viewLoaded = true"を置くだけで、自分で試してみることができます。 –

+1

RE: '//注:[1]というラベルの付いたすべてのステップとは異なり、私は同じ約束に添付された.done()の正式な注文はないと信じています。 2012年のjQueryのDeferred/Promise実装のうち、今度は '.done'呼び出しが追加された順に実行されます。 jQDocs:http://j.mp/jQueryDeferredDone – JoeBrockhaus

関連する問題