2014-08-27 51 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); 
}); 

這將允許你使用你在問題中所提供的工作流程。