2011-12-11 23 views
9

Quale sarebbe il modo migliore per garantire che la mia raccolta rimanga memorizzata nella cache e quindi venga recuperata solo una volta?collezioni memorizzazione nella cache in backbone.js?

Devo implementare una sorta di livello di cache? Devo condividere la variabile Collection per ovunque sia necessario? Posso fidarmi delle impostazioni di jQuerys AJAX? ($.ajaxSetup ({ cache: true });)

La collezione di base come sembra in questo momento:

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

La taglia è ON! Cercando di avere più opinioni su questo argomento! – Industrial

+0

Vuoi mantenere la tua raccolta memorizzata nella cache sul browser utilizzando localStorage o semplicemente assicurarti che la raccolta sia un singleton e che ne hai sempre bisogno chiamerà la stessa istanza già recuperata? –

risposta

16

vorrei implementare una sorta di gestore di collezioni nel tuo caso:

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]; 
    } 
    } 
})(); 

Qui il gestore è responsabile per istanziare collezioni e recupero. Quando si chiama:

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

si ottiene un'istanza di raccolta di esempio con dati già recuperati. Ogni volta che hai bisogno di questa raccolta, puoi chiamare di nuovo il metodo. Otterrai quindi la stessa istanza esatta senza bisogno di recuperarla di nuovo.

Questo è solo un esempio di gestore molto semplice e ci sono molte funzionalità aggiuntive che è possibile implementare e migliorare.

Consiglio vivamente di non gestire questo problema a un livello inferiore (ad esempio il livello di trasporto di $ .ajax). Se lo fai, si dovrebbe evitare che la vostra collezione di ottenere recuperati più volte, ma si finisce per avere diverse istanze del modello con lo stesso ID galleggianti intorno la vostra applicazione. Ogni istanza di raccolta creerebbe i propri modelli.

In una CouchApp al momento sto lavorando, ho anche trovato necessario evitare istanze di modello duplicate in raccolte diverse (diverse viste db possono restituire gli stessi dati del modello). Ciò è stato risolto con una raccolta separata nel gestore, che tiene traccia di tutti i modelli già caricati nell'applicazione.

Ultimo ma non meno importante si potrebbe considerare l'implementazione di un metodo di aggiornamento nelle vostre collezioni o il manager che gestirà l'aggiornamento della collezione dal server. Se si esegue questa operazione con il metodo di recupero, l'intera raccolta viene reimpostata, quindi tutti i modelli vengono distrutti e quindi ricreati. Questo è un male se hai modelli di questa collezione a cui fai riferimento da qualche altra parte nell'app (come fai tipicamente). Quelle istanze sono obsolete e duplicate nella tua app allora. Il metodo di aggiornamento controlla se le istanze con l'id in entrata sono già presenti nella collezione curent. Se è così sono aggiornati, altrimenti vengono aggiunti.

0

Si può cercare di salvare la vostra collezione in localStorage. Ecco il link (http://documentcloud.github.com/backbone/#examples-todos).

L'applicazione utilizza un adattatore LocalStorage per salvare in modo trasparente tutte le Todos all'interno del browser, invece di inviarli al server.

Spero che aiuta :)

2

Se per la memorizzazione nella cache si intende effettivamente un singleton, in modo da poter fare riferimento allo stesso elenco di domini da più posizioni in un'applicazione JS modulare, per questo viene utilizzato RequireJS. È possibile separare la vostra collezione ad essere un modulo nell'applicazione, che poi richiedono ovunque lo si utilizza.In pseudocodice:

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

La funzione di callback sarà sempre la stessa istanza si restituiti quando si definisce il modulo myCollection. Associare a quell'istanza da tutte le visualizzazioni e ogni volta che viene aggiornato, tali visualizzazioni riceveranno un trigger di evento e potranno aggiornarsi.

+0

Questo non causerebbe un aggiornamento? Supponiamo che il tuo modulo di raccolta sia definito come 'return Backbone.Collection.extend ({model: myCollection, url: app.baseUrl() + 'myCollection'});' Come si ottiene un altro recupero? – seebiscuit

+0

Dipende da dove stai chiamando _.fetch() _. In questo caso, in realtà, si vorrebbe restituire un'istanza dalla funzione di fabbrica del modulo di raccolta e quindi tale istanza sarebbe condivisa tra diverse viste. –

0

Una soluzione semplice sarebbe quella di creare una variabile globale per la raccolta in modo che tutto il codice javascript utilizzi la stessa variabile.

Basta prendere la collezione al caricamento della pagina

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

Dal var non viene utilizzato per dichiarata myCollection, allora diventa una variabile globale.

Naturalmente questa è una semplice implementazione. Esistono implementazioni più robuste, ma a seconda delle esigenze, potrebbero essere eccessive.

0

Ho finito per fare qualcosa di simile alla soluzione di ProTom. Invece di inizializzare dinamicamente una raccolta basata sul nome, ho deciso di utilizzare solo una funzione per impostare la raccolta. Attraverso la mia applicazione, avevo bisogno di inizializzare le raccolte in modo diverso a seconda di dove proveniva. Questo si è rivelato il modo migliore per i miei bisogni. Ecco il CoffeeScript:

cache:

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

Usage:

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