2013-03-21 71 views
4

所以我的问题是,我的功能中从我的路由器通风口/事件聚合器被解雇的集合不能访问我的主集合的提取模型。骨干,收集模型不能从路由器发出的功能访问通风口

我的猜测是这是一个异步调用问题,但是我怎样才能让它通风的函数调用WAITS,直到在执行之前获取集合/模型?或者甚至是我的问题?

这是我的相关代码。我正在使用require.js和backbone来创建一个模块化的AMD应用程序。非常感谢你提前:

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?! 
} 

回答

1

您可以使用fetch返回的jQuery Promise来帮助您了解两个集合何时被提取。

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调用由,他们都将等到藏品被取出,并以正确的顺序执行。

+0

嗯,这似乎是一个很好的开始。如果我从应用内导航到网址,那么事情就像他们应该的那样工作,而且你的方法非常棒。然而,如果我从页面外部导航到该URL,那么返回的数组仍然很大,很胖并且空着,让我很生气。任何想法为什么会发生?这一定是因为我认为其余部分大部分都不是正确的? – 2013-03-21 21:44:03

+0

@CameronStrandberg在审查我的代码后,我想我发现了一个问题。当应用程序启动时,您可以在设置'this.fetchingCollectionTwo'之前到'when'代码。当你将undefined传递给'when'时,它将它视为已解决的承诺。看起来你不需要等到第一个集合被获取第二个集合,除非你可能遗漏了一些代码......如果没有,请尝试更新后的代码,它保证两个promise都将在任何'当'电话。 – 2013-03-22 00:06:32

+0

不,对不起我的朋友,这也不起作用。数组仍然是空的。 这绝对是一个异步问题。如果我通过地址更改功能在console.log上放置超时,我会在日志中获取模型。没有这个,addressChange函数在检索模型之前就简单地触发了。我理解等待fetch获得成功的概念,但通过vent addressChange函数触发的所有内容似乎都不知道它在等待什么。 – 2013-03-22 00:43:41

0

我想我解决了它。基本上,我现在调用函数中的$。当function--

像这样:

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

功能从通话时启动里面,然后等待,直到执行完毕任何事情之前完成功能。现在工作!感谢所有人的帮助,尤其是你保罗。