Backbone:从路由器中的 URL 获取未定义,但当集合从变量中获取 JSON 时它有效

Backbone: fetching from URL in router gets undefined, but it works when collection gets JSON from a variable

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

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

我看到的是,当我使用 JSON 变量时,show function 工作正常,但是当我从 URL 获取时,show function 在 [= 之后执行18=]成功。

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

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

// 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});

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

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

基本上:

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

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

我认为您 运行 陷入远程数据问题的原因是您试图访问 this.collection 之前它被请求的数据填充。

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

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'));
      }
    });
  }

});