2012-03-20 17 views
12

Me gustaría saber si existe alguna forma mejor de crear varias colecciones obteniendo de un solo archivo JSON grande. Tengo un archivo JSON como este.Recolecciones múltiples de Backbone de un único archivo JSON grande

{ 
    "Languages": [...], 
    "ProductTypes": [...], 
    "Menus": [...], 
    "Submenus": [...], 
    "SampleOne": [...], 
    "SampleTwo": [...], 
    "SampleMore": [...] 
} 

Estoy usando el url/fetch para crear cada colección para cada nodo del JSON anterior.

var source = 'data/sample.json'; 

Languages.url = source; 
Languages.fetch(); 

ProductTypes.url = source; 
ProductTypes.fetch(); 

Menus.url = source; 
Menus.fetch(); 

Submenus.url = source; 
Submenus.fetch(); 

SampleOne.url = source; 
SampleOne.fetch(); 

SampleTwo.url = source; 
SampleTwo.fetch(); 

SampleMore.url = source; 
SampleMore.fetch(); 

¿Alguna mejor solución para esto?

Respuesta

18

Backbone es ideal para cuando su aplicación se ajusta al molde que proporciona. Pero no tengas miedo de darle vueltas cuando tenga sentido para tu aplicación. Es una biblioteca muy pequeña. Hacer solicitudes GET repetitivas y duplicadas solo para adaptarse al molde de la red troncal es probablemente prohibitivamente ineficiente. Confirmar jQuery.getJSON o su biblioteca AJAX básica favorito, junto con algunos metaprogramming básica de la siguiente manera:

//Put your real collection constructors here. Just examples. 
var collections = { 
    Languages: Backbone.Collection.extend(), 
    ProductTypes: Backbone.Collection.extend(), 
    Menus: Backbone.Collection.extend() 
}; 

function fetch() { 
    $.getJSON("/url/to/your/big.json", { 
     success: function (response) { 
      for (var name in collections) { 
       //Grab the list of raw json objects by name out of the response 
       //pass it to your collection's constructor 
       //and store a reference to your now-populated collection instance 
       //in your collection lookup object 
       collections[name] = new collections[name](response[name]); 
      } 
     } 
    }); 
} 

fetch(); 

Una vez que usted ha llamado fetch() y la devolución de llamada asyn ha completado, puede hacer cosas como collections.Menus.at(0) para llegar al modelo cargado instancias.

+0

¡Ja! Grandes mentes. – nrabinowitz

+0

¡Agradable! Simulanswer! –

14

Su enfoque actual, además de ser bastante largo, arriesga recuperar el archivo grande varias veces (el almacenamiento en caché del navegador no siempre funcionará aquí, especialmente si la primera solicitud no se completó para el siguiente) .

creo que la opción más fácil es ir con jQuery recta, en lugar de la espina dorsal, a continuación, utilizar .reset() en sus colecciones:

$.get('data/sample.json', function(data) { 
    Languages.reset(data['Languages']); 
    ProductTypes.reset(data['ProductTypes']); 
    // etc 
}); 

Si quisiera reducir el código redundante, usted puede poner su colecciones en un espacio de nombres como app y luego hacer algo como esto (aunque podría ser un poco demasiado inteligente para ser legible):

app.Languages = new LanguageCollection(); 
// etc 

$.get('data/sample.json', function(data) { 
    _(['Languages', 'ProductTypes', ... ]).each(function(collection) { 
     app[collection].reset(data[collection]); 
    }) 
}); 
4

Usted puede hacer esto fácilmente con un método de análisis. Configure un modelo y cree un atributo para cada colección. No hay nada que diga que el atributo de modelo debe ser una sola pieza de datos y no puede ser una colección.

Cuando ejecuta su búsqueda, devolverá toda la respuesta a un método de análisis que puede anular creando una función de análisis en su modelo. Algo así como:

parse: function(response) { 
    var myResponse = {}; 
    _.each(response.data, function(value, key) { 
     myResponse[key] = new Backbone.Collection(value); 
    } 

    return myResponse; 
} 

También podría crear nuevas colecciones a nivel global o en algún otro espacio de nombres si prefiere no los tiene contenida en un modelo, pero eso depende de ti.

Para llegar desde el modelo posterior que sólo tendría que hacer algo como:

model.get('Languages'); 
+0

Nuestro servidor me da objetos anidados masivamente en desenvolver en análisis y agregar a colecciones según sea necesario. – tkone

6

Creo que se puede resolver su necesidad y todavía estancia en el paradigma Backbone, creo que una solución elegante que se ajusta a mi es crear un Model que fetch la gran JSON y lo utiliza para fetch todo el Collections en su caso change:

var App = Backbone.Model.extend({ 
    url: "http://myserver.com/data/sample.json", 

    initialize: function(opts){ 
    this.languages = new Languages(); 
    this.productTypes = new ProductTypes(); 
    // ... 

    this.on("change", this.fetchCollections, this); 
    }, 

    fetchCollections: function(){ 
    this.languages.reset(this.get("Languages")); 
    this.productTypes.reset(this.get("ProductTypes")); 
    // ... 
    } 
}); 

var myApp = new App(); 
myApp.fetch(); 

se tiene acceso a través de todas sus colecciones:

myApp.languages 
myApp.productTypes 
... 
+0

Aunque la abstracción del modelo es bastante atractiva, no me gusta este enfoque. Los datos nunca se almacenarán en su estructura actual ... se dividirán en diferentes colecciones. También podría usar .json(). El propósito de un modelo es almacenar 'algo' ¿no? – backdesk

0

columna vertebral-relacional proporciona una solución dentro de la columna vertebral (sin utilizar jQuery.getJSON), que podría tener sentido si ya lo está utilizando. Respuesta corta al https://stackoverflow.com/a/11095675/70987 que me complacería detallar si fuera necesario.

Cuestiones relacionadas