4

したがって、私の問題は、ルーターベント/イベントアグリゲーターから起動されている関数内のコレクションが、メインコレクションのフェッチされたモデルにアクセスできないことです。

私の推測では、これは非同期呼び出しの問題ですが、実行する前にコレクション/モデルがフェッチされるまで、ベントされた関数呼び出しを WAITS にする方法を教えてください。それともそれも私の問題ですか?

これが私の関連コードです。モジュール式の AMD アプリを作成するために、require.js とバックボーンを使用しています。どうもありがとうございました:

main.js

require(['views/app'], function (AppView) {
window.App = {
    Vent : _.extend({}, Backbone.Events)
};
new AppView();

router.js

    define([
        'backbone',
    ], function(Backbone){

    var MainRouter = Backbone.Router.extend({
    routes: {
      'levelone/:id':'showWork'
    },

    showWork: function (index){
      App.Vent.trigger('addressChange', {
        index: index
      });
   }
});
   return MainRouter;
});

App.js

define([
'backbone',
'views/levelone/LevelOneView',
'views/leveltwo/LevelTwoView',
'views/static/StaticView',
'router'
],
function(Backbone, LevelOneView, LevelTwoView, StaticView, MainRouter){
var AppView = Backbone.View.extend({
    el: $("body"),

    events: {
               ...
    },
    initialize: function(){                 
        new LevelOneView();
        App.router = new MainRouter();
        Backbone.history.start();
    },
   .............

LevelOneView.js

initialize:function() {
    this.getCollection();   
    this.domSetup();

    App.Vent.on('addressChange', this.addressChange, this);
},
getCollection : function(){
    var self = this;
    onDataHandler = function(collection) {
        self.LevelTwoCollectionGrab();
    };

    this.collection = new LevelOneCollection([]);
    this.collection.fetch({ success : onDataHandler, dataType: "jsonp" });
},
// We grab a Level Two Collection here so we can take the ids from it and add them to our Level One collection.
// This is necessary so we can create links between the two levels.
LevelTwoCollectionGrab: function(){
    var self = this;

    this.leveltwocollection = new LevelTwoCollectionBase([]);

    onDataHandler = function(collection){
        self.render();
        self.$el.animate({
            'opacity': 1
        }, 1200);
        self.renderLevelTwoIds();
        self.setLevelTwoids();
        self.attachLevelTwoLink();
    }
    this.leveltwocollection.fetch({success : onDataHandler, dataType: "jsonp"});
},
renderLevelTwoIds: function(){
    return this;
},
render: function(){
    var pathname = window.location.hash;

    this.setModelId(this.collection.models);
    this.addPositionsToIndex();
    this.determineModels();
    this.attachLevelTwoLink();
    ....... 
},      

addressChange: function(opts){

console.log(this.collection.models)
//returns a big fat empty array. WHY?!
}
4

2 に答える 2

1

によって返される jQuery Promises を使用してfetch、両方のコレクションがいつフェッチされるかを知ることができます。

initialize:function() {
    this.getCollection();   
    this.domSetup();

    App.Vent.on('addressChange', this.addressChange, this);
},
getCollection : function(){
    var self = this;

    console.log('should be first');

    this.collection = new LevelOneCollection([]);
    this.fetchingLevelOne = this.collection.fetch({ dataType: "jsonp" });
    this.fetchingLevelTwo = this.leveltwocollection.fetch({ dataType: "jsonp"});

    // wait for both collections to be done fetching.
    // this one will always be called before the one in addressChange
    $.when(this.fetchingCollectionOne, this.fetchingCollectionTwo).done(function(){
        console.log('should be second');
        self.render();
        self.$el.animate({
            'opacity': 1
        }, 1200);
        self.renderLevelTwoIds();
        self.setLevelTwoids();
        self.attachLevelTwoLink();
    });
},

renderLevelTwoIds: function(){
    return this;
},
render: function(){
    var pathname = window.location.hash;

    this.setModelId(this.collection.models);
    this.addPositionsToIndex();
    this.determineModels();
    this.attachLevelTwoLink();
    ....... 
},      

addressChange: function(opts){
    var self = this;

    // wait for both collections to be done fetching.
    // this one will always be called AFTER the one in getCollection
    $.when(this.fetchingCollectionOne, this.fetchingCollectionTwo).done(function(){
        console.log('should be third');
        console.log(self.collection.models);
    });
}

これの良いところは、ユーザーがアドレスバーに非常に速く入力し、いくつかのaddressChange呼び出しが行われた場合、コレクションが取得されるまで待機し、適切な順序で実行されることです。

于 2013-03-21T19:31:12.940 に答える
0

私はそれを解決したと思います。基本的に、私は今 $.when 関数内で関数を呼び出しています--

そのようです:

    $.when(this.collection.fetch(), this.leveltwocollection.fetch()).done(function(){
        $.when(self.render()).done(function(){
            _.each(self.collection.models, function(model){
                var wpid = model.get('id'),
                    bbid = model.id;
                if (wpid == index){
                    window.App.InfoPos.pos5 = bbid;
                    var modelinfo = model.toJSON();
                    $('.box5').empty();
                    $('.box5').html(tmplOne(modelinfo));
                    self.$el.animate({
                        'opacity': 1
                    }, 1200);
                }
            });             
        });
    });

この関数は when 呼び出しの内部から起動し、完了するまで待機してから、done 関数で何かを実行します。今すぐ動作します!助けてくれてありがとう、特にポール。

于 2013-03-22T16:00:00.667 に答える