骨干响应SOMETIMES返回空

时间:2012-05-05 14:58:54

标签: jquery backbone.js tastypie

Backbone的问题不一致。我已经在我的集合上的fetch方法中添加了一个console.log,所以我知道服务器总是提供数据,但有时我的视图无法看到该信息,或者显示this.model.models.length到当我知道fetch返回对象时,为零。

我无法弄清楚为什么我会在fetch和试图查看它们之间删除对象,所以希望有人可以提供帮助。

我的路由器看起来像这样:

Router = Backbone.Router.extend({
    routes: {
       ""              : "index",
       "/"             : "index",
       "testing"       : "index",
       "follow/:type/" : "follow"
    },

    follow: function(type) {
        switch(type) {
            case "companies":
               this.followedItems = new FollowedCompanies();
               break;
            case "software":
               this.followedItems = new FollowedSoftware();
               break;
            case "hardware":
               this.followedItems = new FollowedHardware();
               break;
            case "tags":
               this.followedItems = new FollowedTags();
               break;
            case "people":
               this.followedItems = new FollowedPeople();
               break;
            default:
        }
        title = type.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
        this.followedItems.fetch({
            success: function(data) {
            },
            error: function(data) {
                console.log("Error: " + data);
            }
        });
        this.followView = new FollowView({
            model: this.followedItems,
            el: $("#activityFeed"),
            title: title
        });
    }
});

    var router = new Router();
    Backbone.history.start();

模型/控制器,为简洁起见只剪了一个,但都是一样的,甚至一个是不一致的:

var FollowedSoftware = Backbone.Collection.extend({
    url: '/api/v1/follow_software/?format=json',
    model: TestFollowing,
    parse: function(resp) { 
          console.log(resp.objects); 
          return resp.objects; 
    }
});

我的观点如下:

var FollowView = Backbone.View.extend({
    template: _.template($("#FollowHeaderTemplate").html()),
    initialize: function() {
        var self = this;
        $(self.el).slideUp('fast', function() {
            self.model.fetch(); // Put here for to help?  Doesn't matter if it's here or not really. 
            $(self.el).html(self.render());
        });
        $(self.el).slideDown('slow');
        // this.model.reset();
    },
    render: function() {
        var self = this;
        $(this.el).html(new FollowHeaderView().render({title: this.options.title}).el);
        console.log(this.model.models);
        $(self.el).append(new FollowHeaderView({title: this.options.title}).render());
        _.forEach(this.model.models, function(item) {
             $(self.el).append(new FollowedItemView({model: item}).render().el);
        });
    }
})

var FollowHeaderView = Backbone.View.extend({
    template: _.template($("#FollowHeaderTemplate").html()),
    render: function() {
        $(this.el).html(this.template({"title": title}));
        return this;
    }
})

var FollowedItemView = Backbone.View.extend({
    template : _.template( $("#FollowedTemplate").html()),
    render: function() {
        $(this.el).html(this.template({"item" : this.model.toJSON()}))
        return this;
    }
});

即使只是做“软件”路线,有时它也有效,有时则不然。 fetch中的console.log方法始终返回工作数据,但视图中的console.log有时只会返回。

我不是在客户端或服务器上的任何地方缓存任何东西,但我无法使这项工作保持一致。在我的.fetch调用中,我添加了成功和错误回调,但错误回调永远不会触发。我没有覆盖任何地方的同步。我正在使用Backbone的0.9.2,而提供服务器由Django-Tastypie提供支持,它运行良好(并且在其他一些具有相同代码的模型上完美运行。)

可能与switch语句有关,但我不知道它会怎么样,并且为每个'type'定义一个路径似乎很愚蠢(尽管我必须这样做)。

我错过了什么吗?

2 个答案:

答案 0 :(得分:4)

在路由器的follow方法结束时,您正在调用fetch,然后立即初始化您的视图。您应该初始化视图,调用集合上的fetch,然后将视图的render方法绑定到集合的"reset"事件。流是异步的,应该相应地处理。

以下是绑定到reset事件的示例,而不是必须在fetch上实现成功/错误方法(通常不必执行此操作)。

var FollowView = Backbone.View.extend({
    template: _.template($("#FollowHeaderTemplate").html()),
    initialize: function() {
        var self = this;
        $(self.el).slideUp('fast', function() {
            self.model.fetch(); // Put here for to help?  Doesn't matter if it's here or not really. 
            $(self.el).html(self.render());
        });
        $(self.el).slideDown('slow');

        // **ADDED BY lupefiasco**
        self.model.on('reset', function() {
            self.render();
        }, this);
    },
    render: function() {
        var self = this;
        $(this.el).html(new FollowHeaderView().render({title: this.options.title}).el);
        console.log(this.model.models);
        $(self.el).append(new FollowHeaderView({title: this.options.title}).render());
        _.forEach(this.model.models, function(item) {
             $(self.el).append(new FollowedItemView({model: item}).render().el);
        });
    }
})

旁注

您正在重新初始化对路由/follow/:type的每次调用的视图,这非常好,但您需要在初始化新视图之前取消绑定旧视图。所以做这样的事情。

if (this.followView != null) {
     this.followView.off(); // old view is now unbound
}
this.followView = new FollowView();

您不需要在构造函数中传入视图的根元素。只需通过el属性在视图中定义它,Backbone就会自动为您设置$el(“jQuerified”版本)。

var FollowedItemView = Backbone.View.extend({
    template : _.template( $("#FollowedTemplate").html()),
    el: '#activityFeed',
    render: function() {
            this.$el.html(this.template({"item" : this.model.toJSON()}))
            return this;
    }
});

当您通过model属性传递时,您将通过collection属性将您的集合传递给视图。我不认为这在功能方面有很大的不同,但它是best practice

答案 1 :(得分:0)

在从服务器获取模型之前,您正在视图中访问该模型。尝试在success来电的fetch回调中初始化您的观点。

E.g。

var my = this;
this.followedItems.fetch({
  success: function(model) {
    my.followView = new FollowView({
      model: model,
      el: $("#activityFeed"),
      title: title
    });
  }
});