2012-03-20 7 views
12

Vorrei sapere se esiste un modo migliore per creare raccolte multiple recuperando da un unico grande file JSON. Ho un file JSON come questo.Recupero di raccolte multiple backbone da un singolo file JSON grande

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

Sto utilizzando l'url/fetch per creare ogni raccolta per ogni nodo del JSON sopra.

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

Qual è la soluzione migliore?

risposta

18

Backbone è perfetto per quando la tua applicazione si adatta allo stampo che fornisce. Ma non aver paura di aggirarlo quando ha senso per la tua applicazione. È una libreria molto piccola. Effettuare richieste GET ripetitive e duplicate solo per adattarsi allo stampo di backbone è probabilmente proibitivo inefficiente. Partenza jQuery.getJSON o la vostra libreria preferita base AJAX, in coppia con un certo metaprogrammazione base come segue:

//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 volta che hai chiamato fetch() e la richiamata asyn ha completato, si possono fare cose come collections.Menus.at(0) per arrivare al modello caricato le istanze.

+0

Ha! Grandi menti. – nrabinowitz

+0

Bello! Simulanswer! –

14

Il tuo approccio attuale, oltre ad essere piuttosto lungo, rischia di recuperare il file di grandi dimensioni più volte (il caching del browser non funzionerà sempre qui, soprattutto se la prima richiesta non viene completata dal momento in cui si effettua il successivo) .

penso che l'opzione più semplice è quello di andare con jQuery dritto, piuttosto che Backbone, quindi utilizzare .reset() sulle vostre collezioni:

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

Se si voleva ridurre il codice ridondante, si può mettere il raccolte in uno spazio dei nomi come app e poi fare qualcosa di simile (anche se potrebbe essere un po 'troppo intelligente per essere leggibile):

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

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

si può facilmente farlo con un metodo di analisi. Imposta un modello e crea un attributo per ogni raccolta. Non c'è niente che dice che l'attributo del tuo modello deve essere un singolo pezzo di dati e non può essere una collezione.

Quando si esegue il recupero, verrà restituita l'intera risposta a un metodo di analisi che è possibile sovrascrivere creando una funzione di analisi nel modello. Qualcosa di simile:

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

    return myResponse; 
} 

Si potrebbe anche creare nuove collezioni a livello globale o in qualche altro spazio dei nomi, se si preferisce non li avete contenuta in un modello, ma che sta a voi.

Per farli dal modello successivo che ci resta che fare qualcosa di simile:

model.get('Languages'); 
+0

Il nostro server mi dà oggetti nidificati in modo massivo in I unwrap in analisi e aggiungo alle collezioni come necessario. – tkone

6

Penso che si possa risolvere il tuo bisogno e ancora soggiorno nella spina dorsale paradigma, penso che una soluzione elegante che si adatta a me è creare un Model che fetch il grande JSON e lo utilizza per fetch tutto il Collections nella sua change evento:

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

si ha accesso a tutte le vostre collezioni attraverso:

myApp.languages 
myApp.productTypes 
... 
+0

Mentre l'astrazione del modello è piuttosto allettante, non mi piace questo approccio. I dati non verranno mai memorizzati nella struttura attuale ... verranno suddivisi in raccolte diverse. Potresti anche usare .json(). Lo scopo di un modello è memorizzare 'qualcosa' giusto? – backdesk

0

spina dorsale-relazionale fornisce una soluzione entro dorsale (senza l'utilizzo di jQuery.getJSON), che potrebbe avere senso se si sta già usando. Risposta breve allo https://stackoverflow.com/a/11095675/70987 che sarei felice di approfondire se necessario.

Problemi correlati