主干:从路由器中的URL获取未定义,但当集合从变量获取JSON时,它就可以工作



通过存储在变量中的JSON,我可以从名为show: function(id)的路由器函数中获得当前id的名称。然而,当我从URL而不是使用JSON变量获取集合时,我会得到一个未定义的TypeError。

console.log(this.collection.get(id).get('name'));

我所看到的是,当我使用JSON变量时,show function工作正常,但当我从URL获取时,show functionfetch成功后执行。

我做错了什么?为什么从URL获取未定义?我怎样才能让它工作?

下面的代码是虚构的,它只显示了我代码的相关部分。请参阅代码块末尾的两种情况
jsFiddle此处

// Data 1 with variable
var heroes = [
  {"id": "1", "name": "Batman"},
  {"id": "2", "name": "Superman"},
];
// Data 2 from url: http://example.com/heroes.json
[
  {"id": "1", "name": "Batman"},
  {"id": "2", "name": "Superman"},
];
HeroesCollection = Backbone.Collection.extend({
  model: HeroesModel,
  url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
  // I use two shows to graphic this example
  routes: {
    '': 'index',
    ':id': 'show'
  },
  initialize: function(options) {
    this.collection = options.collection;
    this.collection.fetch();
    // this.collection.fetch({async:false}); this fixes my problem, but I heard it is a bad practice
  },
  index: function() {
  },
  show: function(id) {
    console.log(this.collection.get(id).get('name'));
        // Case #1: When Collection loads from a Variable 
        // id 1 returns: 'Batman'
        // Case #2: When Collection fetchs from URL, id 1 returns:
        // TypeError: this.collection.get(...) is undefined 
  }
});
// Case #1: collection loads JSON from a variable
var heroesCollection = new HeroesCollection(heroes);
// Case #2: collection loads JSON with fetch in router's initialize
// var heroesCollection = new HeroesCollection();
var heroesRouter = new HeroesRouter({collection: heroesCollection});

这个怎么样?这已经有一段时间了,但这似乎是一种更好的方法来实现你想要实现的目标。基本概念是,一旦你导航到你的表演路线,它就会执行表演。这个方法将创建一个新的空集合,然后为其获取数据。同时,我们传递一个成功方法(如François所示),该方法将在JSON(创建一个Heros集合)完成请求时执行。

我相信,您遇到远程数据问题的原因是,在使用请求中的数据填充此集合之前,您正试图访问该集合。

您必须记住,请求是异步的,这意味着在处理请求时代码将继续执行。

HeroesCollection = Backbone.Collection.extend({
  model: HeroesModel,
  url: 'http://example.com/heroes.json'
});
HeroesRouter = Backbone.Router.extend({
  routes: {
    '': 'index',
    ':id': 'show'
  },
  index: function() {
  },
  show: function(id) {
    this.herosCollection = new HerosCollection();
    this.herosCollection.fetch({
      success: function(collection, response, options) {
        console.log(this.get(id).get('name'));
      }
    });
  }
});

当集合结束加载时,您需要触发路由器的"show"函数。this.collection.fetch({async:false});修复了您的问题,因为整个javascript代码都在等待(async:false)ajax调用结束,然后再继续。

另一个也是最好的解决方案是,在尝试使用结果之前,等待您的集合被提取。

基本上:

MyCollection.fetch({
   success: function(model, reponse) {
      // do wtv you want with the result here or trigger router show method...
   }
});

最新更新