Backbone:从路由器中的URL获取是未定义的,但是当集合从变量中获取JSON时它会起作用

时间:2016-03-25 10:29:27

标签: json backbone.js fetch

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

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

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

我做错了什么?为什么从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});

2 个答案:

答案 0 :(得分:1)

当集合结束加载时,您需要触发路由器的“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...
   }
});

答案 1 :(得分:1)

这个怎么样?这已经有一段时间了,但这似乎是一种更好的方法来实现你想要实现的目标。基本概念是,一旦您导航到您的节目路线,它将执行show。此方法将创建一个新的空集合,然后为其获取数据。与此同时,我们传递了一个成功方法(如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'));
      }
    });
  }

});