2011-12-11 127 views
9

確保我的集合保持緩存並因此只獲取一次的最佳方式是什麼?在backbone.js中緩存集合?

我應該實現某種緩存層嗎?我應該將Collection變量分享給需要的地方嗎?我可以信任jQuerys AJAX設置嗎? ($.ajaxSetup ({ cache: true });

基本款,因爲它看起來現在:

theCollection = Backbone.Collection.extend({ 
    model: theModel, 
    url: "source.json" 
}); 

if (typeof myCollection === 'undefined') { 
    var myCollection = new theCollection; // Only allow it to be created once 
} 
+0

賞金已打開!希望得到更多關於這個問題的意見! – Industrial

+0

您是否想使用localStorage將您的集合緩存在瀏覽器上,或者只是確保集合是單例集合,並且始終需要它將調用已獲取的同一個實例? –

回答

16

我會實現一種集經理,你的情況:

var manager = (function(){ 

    var constructors = { 
    'example': ExampleCollection 
    }; 
    var collections = {}; 

    return { 
    getCollection: function(name) { 
     if(!collections[name]) { 
     var collection = new constructors[name](); 
     collection.fetch(); 
     collections[name] = collection; 
     } 
     return collections[name]; 
    } 
    } 
})(); 

這裏的經理負責實例收集和獲取它們。當您撥打電話:

var exampleCollection = manager.getCollection('example'); 

您將獲得一個示例集合實例,其中已獲取數據。只要你再次需要這個集合,你可以再次調用這個方法。然後您將獲得完全相同的實例,無需再次獲取。

這只是一個非常簡單的管理器示例,還有很多其他功能可以實現和增強。

我強烈建議不要在較低級別處理此問題(例如$ .ajax的傳輸層)。如果你這樣做了,你會阻止你的集合被多次獲取,但是最終會有不同的模型實例在你的應用程序中浮動。每個集合實例都會創建它自己的模型。

在我目前正在研究的CouchApp中,我還發現有必要在不同的集合中防止重複的模型實例(不同的數據庫視圖可以返回相同的模型數據)。這已經通過在管理器中有一個單獨的集合來解決,該集合跟蹤已經加載到應用程序中的所有模型。

最後但並非最不重要的是,您可能會考慮在您的集合中執行刷新方法,或者將處理從服務器更新集合的管理器。如果使用fetch方法執行此操作,則整個集合將被重置,以便所有模型都被銷燬並重新創建。如果您在應用程序的其他位置引用了此集合中的模型(如您通常所做的那樣),那麼這很糟糕。那些實例已過時,然後在您的應用中重複。刷新方法使用傳入的id檢查其他實例是否已存在於curent集合中。如果是這樣,他們被更新,否則他們被添加。

0

你可以嘗試保存您的收藏中的localStorage。這裏是鏈接(http://documentcloud.github.com/backbone/#examples-todos)。

該應用程序使用LocalStorage適配器將所有待辦事項透明地保存在瀏覽器中,而不是將它們發送到服務器。

我希望它能幫助:)

2

如果緩存你實際上意味着一個單身人士,以便您可以從模塊化JS應用程序中的多個位置引用相同的域列表,我們使用RequireJS。您可以將您的收藏分離爲應用程序中的模塊,無論您在何處使用它,都需要使用該模塊。在僞代碼:當你定義MyCollection的模塊

require(["myCollection"], 
    function(myCollection) { 
     var MyView = Backbone.View.extend(); 
     new MyView({ 
      collection: myCollection 
     }).render(); 
    } 
); 

回調函數總是會得到你返回相同的實例。從所有視圖綁定到該實例,並且每當它刷新時,這些視圖都會獲得一個事件觸發器並可以自行更新。

+0

這不會導致刷新?假設你的收集模塊被定義爲'return Backbone.Collection.extend({model:myCollection,url:app.baseUrl()+'myCollection'});'你如何繞過另一個獲取? – seebiscuit

+0

取決於你打電話給_.fetch()_。實際上,在這種情況下,您實際上想要從收集模塊工廠函數中返回實例,然後該實例將在不同視圖之間共享。 –

0

一個簡單的解決方案是爲您的集合製作一個全局變量,以便您的所有JavaScript代碼將使用相同的變量。

只是獲取集合加載頁面時

$(function() { 
    myCollection = theCollection(); 
    myCollection.fetch(); 
}); 

由於VAR不用於申報MyCollection的,然後就變成了全局變量。

當然這是一個簡單的實現。有更強大的實施,但取決於您的需求,它們可能是矯枉過正。

0

我最終做了類似於ProTom的解決方案。我不是根據名稱動態初始化一個集合,而是決定使用一個函數來設置集合。通過我的應用程序,我需要根據它來自何處對它們進行不同的初始化。這被證明是滿足我需求的最佳方式。這裏的CoffeeScript的:

緩存:

cachedCollections: {} 
getCollection: (key, block) -> 
    collection = @cachedCollections[key] 
    return collection if collection 
    collection = block() 
    @cachedCollections[key] = collection 
    collection 

用法:

commentCollection = getCollection "comments-#{postId}", -> 
    collection = new CommentCollection 
    collection.url = "/api/posts/#{postId}/comments" 
    collection