如何在开始视图之前等待模型初始化

时间:2015-01-25 08:41:14

标签: javascript backbone.js

我正在制作一个基本的trello克隆。除了登录之外,项目都有一个slug(即www.example.com/1d754b6c')

如果用户访问root,则会在后端创建一个新的slug。然后将用户路由到www..com / 1d754b6c,它发送另一个ajax调用以获取项目ID。然后开始视图。但是我的观点是在slug之前开始 - > ID ajax调用已完成。什么是最好的解决方法? (我目前有一个setTimeout作为临时补丁,我知道这不是一个很好的方法来完成这个)

router.js

Buckets.Routers.PageRouter = Backbone.Router.extend({
    routes: {
        '': 'newProject',
        ':token': 'displayProject'
    },
    newProject: function () {
        new Buckets.Models.Project({});
    },
    displayProject: function (token) {
        var that = this;
        var project = new Buckets.Models.Project({token: token});
        setTimeout(function(){ 
            new Buckets.Views.showProject({
                            model: project
                        });
        }, 500);

    }
});

project.js

Buckets.Models.Project = Backbone.Model.extend({
    url: function() {
        return Buckets.BASE_URL + '/api/projects/' + (this.id)
    },
    initialize: function(options) {
        var that = this;
        if (options && options.token) {
            that.token = options.token
            $.ajax({
                url: Buckets.BASE_URL + '/' + that.token,
                dataType: 'json',
                    success: function( data, status ){
                        that.id = data;
                    },
                    error: function(xhr, textStatus, err) {
                        console.log(xhr);
                    }
                });
        } else {
            $.ajax({
                    url: Buckets.BASE_URL + '/api/projects/new', 
                    dataType: 'json',
                    success: function( data, status ){
                        that.token = data.token;
                        that.id = data.id;
                        Buckets.Routers.router.navigate('/' + that.token, true);
                    },
                    error: function(xhr, textStatus, err) {
                        console.log(xhr);
                    }
                });
        }
        return this;
    },
});

1 个答案:

答案 0 :(得分:0)

尝试使用Backbone.Model.sync.sync()返回Promise,因此您可以充分利用Deffered / Promises标准。

当我想将变量url传递给fetch时,我会覆盖model.fetch()。对于您的实施,我首先删除$.ajax中的initialize()并覆盖fetch,如下所示

Buckets.Models.Project = Backbone.Model.extend({
  fetch: function(options) {
      var that = this;
      if (options && options.token) {
        this.url = Buckets.BASE_URL + '/' + that.token;
      else
        this.url = Buckets.BASE_URL + '/api/projects/new';

      return Backbone.Model.prototype.fetch.call(this, options);
}

.fetch()最终返回sync()的结果,这是一个承诺。这意味着在你的Router中你会这样做:

displayProject: function (token) {
  var that = this;
  var project = new Buckets.Models.Project();
  $.when(project.fetch({token: token})
  // deffered.done() replaces the success callback in your $.ajax
  .done(function() {
    project.id = data;
    new Buckets.Views.showProject({ model: project });
  })
  // deffered.fail() replaces the error callback in your $.ajax
 .fail(function( jqXHR, textStatus, errorThrown) {
   console.log(jqXHR);
 });
}

为了完整起见,您同样重新newProject()

newProject: function () {
  var project = new Buckets.Models.Project();
  $.when(project.fetch({token: token})
  .done(function( data, textStatus, jqXHR ) {
    project.token = data.token;
    project.id = data.id;
    new Buckets.Views.showProject({ model: project });
  })
  .fail(function( jqXHR, textStatus, errorThrown) {
    console.log(jqXHR);
  });
}

试一试。当MarionetteJS的主要贡献者向我推荐时,我开始使用这种获取方法,{{1}}是一个主要的自以为是的Backbone框架。这种方法易于维护且反应灵敏。