Patrón de carga de datos para knockoutjs
-
27-10-2019 - |
Pregunta
Estoy tratando de entender si KnockoutJS funcionará para mi aplicación. Mi modelo de datos (simplificado) es el siguiente:
function topic(data) {
this.id = data.id;
this.queries = ko.observableArray([]);
}
function query(data) {
this.id = data.id;
this.text = data.text;
this.searcher = data.searcherId;
this.postings = ko.observableArray([]);
}
function posting(data, query) {
this.documentId = data.docid;
this.rank = data.rank;
this.snippet = data.snippet;
this.score = data.score;
this.query = query;
this.document = null;
}
function document(data, topic) {
this.id = data.id;
this.url = data.url;
this.topic = topic;
}
Para una dada topic
, Tengo uno o más query
instancias. Cada consulta contiene una lista de posting
instancias. Cada posting
se refiere a un documento. Más de uno posting
puede referirse a un hecho document
siempre y cuando el posting
Las instancias pertenecen a diferentes query
instancias.
Si un posting
se refiere a un nuevo documento (uno aún no recuperado por ningún query
) Me gustaría crear una nueva instancia; Si el document
Ya existe (las ID son únicas), me gustaría reutilizarlo.
Puedo ver algunas alternativas posibles para estructurar los datos JSON devueltos por el servidor:
- Al serializar las publicaciones, primero sea serialice una lista de todos los documentos y actualice la lista de documentos maestros con ellos. Luego, envíe publicaciones con referencias a ID de documento.
- Serialice cada documento por completo como una propiedad de una publicación, y luego averigüe si esa entrada es redundante. Agregue entradas no redundantes a la lista maestra.
¿Cuál es un patrón razonable para serializar los datos? ¿Hay alguna magia de complemento de mapeo que exprese esto sucintamente? Tengo control sobre el servidor que está generando el JSON y puedo estructurar eso de cualquier manera que tenga sentido.
Gracias,
Gene
Solución
Esto es lo que terminé haciendo para implementar la opción 1:
function idField(data) {
return ko.utils.unwrapObservable(data.id);
}
function createMapping(type, context) {
return {
key: idField,
create: constructor(type, context)
}
}
function constructor(type, context) {
return function(options) {
return new type(options.data, context);
}
}
function createReferenceMapping(collection) {
return {
key: idField,
create: lookup(collection)
}
}
function lookup(collectionOrClosure) {
return function(options) {
var collection = (typeof collectionOrClosure == 'function') ? collectionOrClosure() : collectionOrClosure;
var object = collection.findById(options.data.idref);
if (object == null)
console.log("Error: Could not find object with id " + options.data.idref + " in ", collection);
return object;
}
}
Llamo a este código de la siguiente manera:
var mapping = {
people: createMapping(Searcher),
topics: createMapping(Topic, this),
activeTopic: createReferenceMapping(function(){return self.topics();})
};
this.dataChannel.loadModel(function(data) {
ko.mapping.fromJS(data, mapping, this);
}
Esto se encarga de crear nuevas instancias (a través del constructor
función) y buscar las existentes a través de lookup
.
Otros consejos
Consulte EntitySpaces.js, hay un video que puede ver, admite modelos de datos jerarquciales completos e incluso generará su servicio WCF JSON, también admite API REST.
Un marco de JavaScript Orm (acceso a datos) que utiliza knockout