无法使用backbone.js正确获取集合

时间:2012-07-23 09:28:55

标签: javascript backbone.js backbone.js-collections

请阅读到最后(我在最后提到console.log)

模特:

// Spot model:
define([
  'jquery',    
  'underscore',
  'backbone'  
], function($, _, Backbone){
    var Spot = Backbone.Model.extend({
        url: function(){
            if (this.get('id') !== null){
                return '/spot/' + this.get('id');
            }
            return '/spots';
        },
        idAttribute: "id",
        defaults: {
            id: null,
            details:{
                name: "school",
                type: 4,
                rank: 3,
                comment: null
            },
            location:{
                    address: '',
                    lat: 70.345,
                    lng: 90.123
            },
            user:{
                id: 12345,
                name: "magneto"
            }
        },
        parse: function(response){
        /*  var attrs = {
                details: {},
                location: {},
                user: {}
            };
            attrs.id = response.id;

            attrs.details.name = response.details.name;
            attrs.details.type = response.details.type;
            attrs.details.rank = response.details.rank;
            attrs.location.lat = response.location.lat;
            attrs.location.lng = response.location.lng;
            return attrs; */
        }
    });
    return Spot;
});

集合:

// Spots collection:
define([
  'jquery',    
  'underscore',
  'backbone',  
  'models/Spot'
], function($, _, Backbone,spot_model){
    var Spots = Backbone.Collection.extend({
        model: spot_model,
        url:
            function() {
            return '/projects/FE/spots';
          },
        parse: function(response){
    /*      var parsed = [],
              key;

          _.each(response, function (value) {
              parsed.push(value);
          }, this);

          return parsed;*/
        },
      comparator: function(spot){
        return spot.rank;
      }
    });
    return Spots;
});

观点:

// inside our view named: SpotsView
define([
  'jquery',
  'underscore',
  'backbone',
  'mustache',
  'icanhaz',
  'views/spots/Spot',
  'collections/Spots',
  'text!../../../../templates/spots/spots.mustache!strip',
], function($,
            _,
            Backbone,
            mustache,
            ich,
            SpotView,
            Spots,
            SpotsTemplate){
  var SpotsView = Backbone.View.extend({
    //el: $("#container"),
    tagName: "ul",
    initialize: function(){

      console.log('initialize view');
      console.log(this.collection);
      _.bindAll(this,'render');

    },
    render: function(){
      console.log(this.collection);
      console.log('length: ' + this.collection.length);
      console.log('models: ' + this.collection.models);

      _.each(this.collection.models, function (spot) {
            $(this.el).append(new SpotView({model:spot}).render().el);
        }, this);
      return this;
    }
  });
  return SpotsView;
});

在我们的app.js

   var spots = new Spots({model: Spot}),
        spotsview;


    spots.reset();
    console.log(spots.fetch());
    console.log('spots:');
    console.log(spots.length);
    console.log(spots);
    spotsview = new SpotsView({collection: spots});

服务器输出

// SERVER output(s) i tried:
{"id": 666,"details":{"name": "mark","type":4,"rank":3.1,"comment":"nothing"},"location":{"lat":70.123,"lng":90.321,"address":"5th avenue"},"user":{"id":333,"name":"wolverine"}}

// another one i tried:
[{"id": 666,"details":{"name": "mark","type":4,"rank":3.1,"comment":"nothing"},"location":{"lat":70.123,"lng":90.321,"address":"5th avenue"},"user":{"id":333,"name":"wolverine"}}]

// another one:
[{"id":"55","details":{"name":"Dan","type":"6","rank":"-9.9","comment":"myEx"},"location":{"lat":"40.780346","lng":"-73.957657","address":"78, West 86th Stree"}},{"id":"57","details":{"name":"Ron","type":"6","rank":"3.0","comment":"Butch"},"location":{"lat":"40.715569","lng":"-73.832428","address":"1344 Queens Boulevard"}},{"id":"58","details":{"name":"Monk's","type":"11","rank":"9.5","comment":"yesss"},"location":{"lat":"40.805443","lng":"-73.965561","address":"112th and broadway "}}]




// without using "parse" method in the collection and in the model (they are commented) i get:
d
_byCid: Object
_byId: Object
length: 0
models: Array[0]
__proto__: x

// when not commented (parse in both collection and model) i get:
_byCid: Object
_byId: Object
length: 6
models: Array[6]
__proto__: x

// despite it says 6, in the view you can see there are lines:
//console.log(this.collection);  <--- returns the abovee
//console.log('length: ' + this.collection.length); <-- returns 0
//console.log('models: ' + this.collection.models); <--- none

我也尝试从模型中删除所有属性defenitions。仍然没有奏效。 返回值内容类型是:application / json(已验证)并且是有效的json。

我读过: Backbonejs collection length always zero

但是尽管console.log显示0长度,但是:

for(var i=0; i< this.collection.length; i++){
        console.log(this.collection.get(i));
}

不起作用!

我也读过 Did backbone collection automatically parse the loaded data

非常感谢

更新: 我可能已经解决了这个问题:我甚至从模型和集合中删除了“解析”声明并且它工作了:长度:6个SpotsView.js模型:[object Object],[object Object],[object Object], [object Object],[object Object],[object Object]无论哪种方式我都想知道正确使用,如果我做得对,如何在两种情况下以正确的方式使用PARSE(收集和模型明智),你是什么两者都返回(!)。 Tnx

1 个答案:

答案 0 :(得分:0)

Collection.fetch是一个异步操作,因此当您获取一个集合时,将发送一个ajax调用,然后您的代码将继续运行,就像没有发生任何事情一样。

spots.reset(); // emptied your collections

console.log(spots.fetch()); // fetch your collection (why is this inside a console.log???)

console.log('spots:'); // log some text, this will be executed right after your fetch call has been made

console.log(spots.length); // here the fetch call probably hasn't returned yet, so returns 0

console.log(spots); // same as above, so returns an empty collection

spotsview = new SpotsView({collection: spots}); // the collection might or might not get populated by the time you get to rendering so there is probably variation from program run to another

那么如何解决这个问题呢?在视图中,将render函数绑定到集合的reset事件(在每次成功获取或强制重置后启动)。这样,只有在要显示某些内容时,视图才会呈现。

// view's initialize method
initialize: function() {
  ...
  this.collection.on('reset', this.render);
  ...
}