2011-12-11 21 views
9

¿Cuál sería la mejor manera de garantizar que mi colección permanezca almacenada en la memoria caché y, por lo tanto, solo se obtenga una vez?Colecciones de almacenamiento en caché en backbone.js?

¿Debo implementar algún tipo de capa de caché? ¿Debo compartir la variable Collection donde sea que se necesite? ¿Puedo confiar en la configuración jQuerys AJAX? ($.ajaxSetup ({ cache: true });)

La colección básica como se ve en este 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

Bounty is ON! ¡Buscando obtener más opiniones sobre este tema! – Industrial

+0

¿Desea mantener su colección almacenada en la memoria caché en el navegador utilizando localStorage o simplemente asegúrese de que la colección sea singleton y siempre que lo necesite, llame a la misma instancia que ya se haya obtenido? –

Respuesta

16

Me gustaría poner en práctica una especie de gestor de cobros en su 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]; 
    } 
    } 
})(); 

Aquí el gerente es responsable de instanciar colecciones y obtenerlos. Cuando llamas:

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

obtienes una instancia de colección de ejemplo con datos que ya se han obtenido. Siempre que necesite esta colección nuevamente, puede volver a llamar al método. A continuación, obtendrá la misma instancia exacta sin necesidad de buscarla nuevamente.

Este es solo un ejemplo de administrador muy simple, y hay muchas características adicionales que puede implementar y mejorar.

Recomiendo encarecidamente no manejar este problema en un nivel inferior (por ejemplo, la capa de transporte de $ .ajax). Si lo hace, evitaría que su colección se busque varias veces, pero terminará teniendo instancias de modelos diferentes con la misma ID flotando alrededor de su aplicación. Cada instancia de colección crearía sus propios modelos.

En un CouchApp en el que actualmente estoy trabajando, también me pareció necesario evitar instancias de modelos duplicados en diferentes colecciones (diferentes vistas de bases de datos pueden devolver los mismos datos del modelo). Esto se ha solucionado teniendo una colección separada en el administrador, que realiza un seguimiento de todos los modelos que ya están cargados en la aplicación.

Por último, pero no menos importante, podría considerar implementar un método de actualización en sus colecciones o el administrador que se encargará de actualizar la colección del servidor. Si hace esto con el método fetch, toda su colección se restablece para que todos los modelos se destruyan y luego se vuelvan a crear. Esto es malo si tiene modelos de esta colección a los que se hace referencia en otro lugar de la aplicación (como suele hacer). Esas instancias están desactualizadas y duplicadas en su aplicación. El método de actualización comprueba si las instancias con la identificación entrante ya están presentes en la colección actual. Si es así, se actualizan, de lo contrario se agregan.

0

Puede intentar salvar su colección en localStorage. Aquí está el enlace (http://documentcloud.github.com/backbone/#examples-todos).

La aplicación utiliza un adaptador LocalStorage para guardar de forma transparente todos tus objetos dentro de tu navegador, en lugar de enviarlos a un servidor.

espero que ayude :)

2

Si en caché significa realmente un singleton, para que pueda hacer referencia a la misma lista de dominios desde varios lugares en una aplicación JS modular, utilizamos RequireJS para esto. Puede separar su colección para que sea un módulo en la aplicación, que luego necesita donde sea que la use.En pseudocódigo:

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

Su función de devolución de llamada siempre obtendrá la misma instancia que regresó al definir el módulo de myCollection. Enlace a esa instancia desde todas las vistas, y siempre que se actualice, esas vistas obtendrán un activador de evento y pueden actualizarse.

+0

¿No causaría esto una actualización? Supongamos que su módulo de recopilación se define como 'return Backbone.Collection.extend ({model: myCollection, url: app.baseUrl() + 'myCollection'});' ¿Cómo se soluciona otra recuperación? – seebiscuit

+0

Depende de dónde llame _.fetch() _. De hecho, en este caso, realmente desea devolver una instancia desde la función de fábrica de su módulo de colección, y luego esa instancia se compartiría entre diferentes vistas. –

0

Una solución simple sería hacer una variable global para su colección para que todo su código javascript use la misma variable.

Sólo buscar a la colección cuando se carga la página

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

Desde var no se utiliza para declarada myCollection, entonces se convierte en una variable global.

Por supuesto, esta es una implementación simple. Existen implementaciones más robustas, pero según sus necesidades, pueden ser excesivas.

0

Terminé haciendo algo similar a la solución de ProTom. En lugar de inicializar dinámicamente una colección basada en el nombre, decidí simplemente usar una función para configurar la colección. A través de mi aplicación, tuve que inicializar las colecciones de forma diferente dependiendo de dónde venían. Esta resultó ser la mejor manera para mis necesidades. Aquí está la CoffeeScript:

caché:

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

Uso:

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