2014-08-27 82 views
2

我想要类似以下行为:在Backbone Collection中根据需要获取模型?

  1. 调用集合上的get()。
  2. 仅在尚未提取模型的情况下才提取模型。
  3. 返回模型或触发表示它已准备好的事件。

有没有一种标准的方法来做到这一点在骨干?

+0

“标准”的方式是覆盖你想定义不同行为的方法,在这种情况下,集合上的get方法。所以如果我理解正确,你想调用get一个集合,并且如果在内部,该方法在当前集合中找不到该模型,那么从数据源中获取它并将其添加到集合中? – kinakuta 2014-08-27 22:30:35

+0

这是正确的。如果主干已经提供了这种行为,我不会重新发明轮子,这正是我所要求的。 – elplatt 2014-08-28 01:34:27

+0

AFAIK你不能在不重写集合'get'方法的情况下管理它。另外,你将不得不关心异步模型“获取”和同步“获取”行为。 – Evgeniy 2014-08-28 05:31:36

回答

1

骨干没有标准的方法来做到这一点,并要求您修改模型和集合。我知道你没有在问题中提到过jQuery,我只是在它提供的延迟对象功能的例子中使用它,并且可以将它换出来用于任何延迟对象库。

这种方法的问题是收集get()方法将不得不返回一个延期的对象供您使用,而不是模型。这是一种将异步操作构建为集合get()方法的不幸产品。

对于模型,我们需要一种方法来追踪它是否被抓取。为此使用时间戳可能会允许您'超时'模型,并在模型已过期时重新获取它。为此,我们重写模型上的获取方法。

警告:此代码是未经测试,但提供了一种方法来处理这个

var Model = Backbone.Model.extend({ 

    /** 
    * Last fetched public variable 
    * @var {Object} Date || null 
    */ 
    lastFetched : null, 


    /** 
    * Custom fetch always adds a timestamp to the model 
    * when it was last fetched from the server. This 
    * allows us to prevent unnecessary calls to the backend 
    * when a model is still fresh. 
    * @return {Object} jQuery deferred 
    */ 
    fetch : function() { 

     if (_.isNull(this.lastFetched)) { 
      this.lastFetched = new Date().getTime(); 

      return Backbone.Model.prototype.fetch.apply(this, arguments); 
     } else { 
      return new $.Deferred().resolve(); 
     } 
    } 
}); 

收集需要有它的获得覆盖到包括模型获取常规方法。 get方法不会返回模型,而是返回一个延迟对象,该对象可用于在模型准备就绪时链接回调。

var Collection = Backbone.Collection.extend({ 

    model : Model, 

    /** 
    * Custom get retrieves a model if it exists and returns the result 
    * of the models custom fetch method 
    * @param {Integer} id | cid 
    * @return {Object} 
    */ 
    get : function(id) { 
     var model = Backbone.Collection.prototype.get.apply(this, args); 

     if (! model) 
      model = new this.model({id : id}); 

     return { 
      deferred : model.fetch(), 
      model : model 
     }; 
    } 
}); 

使用

var collection = new Collection(), 
    result = collection.get(1); 

result.deferred.done(function() { 
    console.log(result.model); 
}); 

这将允许你使用你在问题中所提供的工作流程。