为什么集合长度为0但是获取成功?

时间:2016-11-01 20:30:09

标签: javascript backbone.js

我的todos.js:

var app = app || {};

(function () {
    'use strict';
    var Todos = Backbone.Collection.extend({
        model: app.Todo,
        url: '/api/todos'
    });
    app.todos = new Todos();
})();

APP-view.js

var app = app || {};
(function($){
    'use strict';
    app.AppView = Backbone.View.extend({
        el: '.todoapp',
        events : {
            'keypress .new-todo': 'createOnEnter'

        },

        initialize: function() {
            this.$input = this.$('.new-todo');
            this.$list = $('.todo-list');
            app.todos.fetch( {
                reset : true
            } );
            this.render();
        },


        render: function(){
            console.log( ' len = ' +  app.todos.length );
            app.todos.each( function(todo){
                this.renderTodo( todo );
            }, this );
        },
...

提取数据

[{
    "_id": "5801",
    "title": "testtitle123",
    "completed": false,
    "__v": 0
}, {
    "_id": "58182",
    "title": "testtitle126",
    "completed": false,
    "__v": 0
}, {
    "_id": "5813",
    "title": "testtitle127",
    "completed": false,
    "__v": 0
}]

成功获取数据(来自http://myip:8000/api/todos)。但是从控制台,长度始终为0.

更新

我尝试了以下代码。但没有'好的'或者'错误'登录控制台。

    var app = app || {};
    (function($){
        'use strict';
        app.AppView = Backbone.View.extend({
            el: '.todoapp',
            events : {
                'keypress .new-todo': 'createOnEnter'

            },

            initialize: function() {
                this.$input = this.$('.new-todo');
                this.$list = $('.todo-list');
                this.listenTo(app.todos, 'sync', this.render);
                app.todos.fetch( {
                    reset : true,
                    context: this,
                    success: function(col, res, op) {
                        console.log( 'OK' );
                    },
                    error: function(col, res, op){
                        console.log( 'error' );
                    }
                } );
            },

            render: function(){
                console.log( ' len = ' +  app.todos.length );
                app.todos.each( function(todo){
                    this.renderTodo( todo );
                }, this );
            },

            renderTodo: function( todo ) {
                console.log( 'render :' + todo.title );
                var todoView = new app.TodoView( { model : todo } );
                this.$list.append( todoView.render().el );
            },
        });

    })(jQuery);

2 个答案:

答案 0 :(得分:1)

fetch是异步的,所以当你立即渲染后,集合仍然是空的。

根据定义,任何需要调用服务器的函数都是异步的。在不锁定浏览器的情况下,它们无法同步。

使用Backbone提供的回调轻松解决此问题:

initialize: function() {
    /** ...snip... */
    app.todos.fetch({ 
        reset: true,
        context: this,
        success: this.render
    });
},

此外,如果从API收到的数据采用以下格式:

{
    data: [
        {...},
        {...}
    ]
}

您需要在集合中提供parse功能:

var Todos = Backbone.Collection.extend({
    model: app.Todo,
    url: '/api/todos',
    parse: function(response) {
        return response.data;
    }
});



var PostCollection = Backbone.Collection.extend({
  url: 'https://jsonplaceholder.typicode.com/posts',
});


var collection = new PostCollection();
collection.fetch({
  reset: true,
  context: this,
  success: function() {
    console.log("Success:", collection.length);
  }
});

Simplest demo of fetching and checking the `length`.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这是因为所有提取都是异步的。所以你的渲染在它取出你的待办事项之前就已经开始了。

完成提取后,您可以重新渲染:

app.todos.fetch().done(function(){
   self.render();
});

您还可以收听模型的同步事件:

this.listenTo(app.todos, 'sync', this.render);

http://backbonejs.org/#Sync