2012-02-03 4 views
5

私は完全にここで何かが欠落している場合がありますが、私は以下の持っている: コレクションを作成した後にbackbone.jsを実行して関数を実行しますか?

  • モデルが1つ(またはそれ以上)を持っている(すべてのJSONは1つのURLからロードされた)

    • 「すべて」のデータをカプセル化モデルそれが建設
    • 私は、データが初期化されるときにコレクション上で実行すると、私の質問は、合成コレクションについてです

    ロードされたいくつかのコードに乗ったデータでインスタンス化されるコレクション。私はコレクションの範囲外でこれを行うことができますが、むしろそれをカプセル化したい(そうでなければ、イニシャライザなどで 'クラス'にする点が何であるか)。

    1. 私はinitialize()機能でそのコードを置くことができると思ったが、モデルが投入されました前にそれが実行されますので、私は、コレクション(this.modelsが空である)を含むモデルにアクセスすることはできません。

    2. 私はイベントにバインドできると考えましたが、初期化後にイベントがトリガーされることはありません。彼らは独自のエンドポイントからfetchのコレクションを読み込んだ場合には、私はそれをしていません、私は既存のデータからコレクションを初期化しています。

    私の質問:それはデータで初期化された直後のコレクション上で実行するコードを初期化するための手順(すなわちthis.modelsが空ではありません)。

    「外部」コードを必要とせずにこれを行うことは可能ですか?

    ここでデモコードがありますが、これはもっとよく説明します。

    var Everything = Backbone.Model.extend({ 
        url: "/static/data/mydata.json", 
        parse: function(data) 
        { 
         this.set("things", new Things(data.things, {controller: this})); 
        } 
    }); 
    
    var Thing = Backbone.Model.extend({ 
    }); 
    
    var Things = Backbone.Collection.extend({ 
        model: Thing, 
        initialize: function(data, options) 
        { 
         // HERE I want access to this.models. 
         // Unfortunately it has not yet been populated. 
         console.log("initialize"); 
         console.log(this.models); 
         // result: [] 
    
         // And this event never gets triggered either! 
         this.on("all", function(eventType) 
         { 
          console.log("Some kind of event happend!", eventType); 
         }); 
        } 
    }); 
    
    var everything = new Everything(); 
    everything.fetch(); 
    
    // Some manual poking to prove that the demo code above works: 
    
    // Run after everything has happened, to prove collection does get created with data 
    setTimeout(function(){console.log("outside data", everything.get("things").models);}, 1000); 
    // This has the expected result, prints a load of models. 
    
    
    // Prove that the event hander works. 
    setTimeout(function(){console.log("outside trigger", everything.get("things").trigger("change"));}, 1000); 
    // This triggers the event callback. 
    
  • 答えて

    7

    は、残念ながらあなたのためのコレクションは、それが適切に最初に初期化されたとのモデルは、イベントがトリガされません意味silent: trueフラグを使用してリセットされた後にのみデータに設定されます。

    あなたが本当に使いたければ、setTimeout(...、0)またはアンダースコアdeferメソッドを使用して、次のブラウザのイベントループに実行したいことを遅らせることで少し気を使うことができます。

    initialize: function(data, options) { 
    
        _.defer(_.bind(this.doSomething, this)); 
    }, 
    
    doSomething: function() { 
    
        // now the models are going to be available 
    } 
    
    +0

    私は、コレクションの構築を同期させることを望んでいました(例えば、それは 'Everything.parse'の次の行で使用できます)。明らかに遅らせることはできません。私は、コレクションからロジックを外さなければならないかもしれません。おそらくBackbone.jsへの変更要求... – Joe

    +0

    'defer'を使うと、webCGMにEventListenerをインストールするのが理想的です。 WebCGMダイアグラムは独立したオブジェクトとしてロードされ、ダムピクチャとしての生活を開始します。イベントの送信を開始するように明示的に指示する必要があります。イベントを送信すると、バックボーンインフラストラクチャにパイプバックできます。私は同じテクニックが他のプラグイン(SVG/PDFなど)とやりとりすることができ、その多くがbroswerでうまくいきませんと思う。 –

    0

    これは古い質問です。私は同様の問題を抱えていて、この解決策を作成する助けがありました:

    set関数を拡張することによって、コレクションのデータが実際のモデルに変換されたときを知ることができます。 setは.addと.resetから呼び出されます。これは、フェッチオプションのresetまたはsetにかかわらず、コレクションクラスをインスタンス化してフェッチからコア関数中に呼び出されることを意味します。

    このようにして、実行フローをハッキングせずに通知を受けるタイミングと方法を制御できます。

    var MyCollection = Backbone.Collection.extend({ 
        url: "http://private-a2993-test958.apiary-mock.com/notes", 
        initialize: function() { 
        this.listenToOnce(this, 'set', this.onInitialized) 
        }, 
    
        onInitialized:function(){ 
        console.log("collection models have been initialized:",this.models) 
        }, 
    
        set: function(models,options){ 
        Backbone.Collection.prototype.set.call(this, models, options); 
        this.trigger("set"); 
        } 
    }) 
    
    //Works with Fetch! 
    var fetchCollection= new MyCollection() 
    fetchCollection.fetch(); 
    
    //Works with initializing data 
    var colData = new MyCollection([ 
         {id:5, name:'five'}, 
         {id:6, name:'six'}, 
         {id:7, name:'seven'}, 
         {id:8, name:'eight'} 
        ]) 
    
    //doesn't trigger the initialized function 
    colData.add(new Backbone.Model({id:9,name:'nine'}; 
    

    注:私たちは.listenToOnceを使用していけない場合は、我々はまた、モデルは、同様のコレクションに追加または変更されるたびに呼び出さonInitializedを取得します。

    関連する問題