Déjame dar una sesión. Nunca uso backbone.js. Sin embargo, tengo el impresionante contenedor IndexedDB YDB-DB y tengo previsto respaldar los frameworks vinculantes de backbone.js y angular.js. Pero parece que no hay mucho que hacer.
Como se sugirió el interrogador, el patrón de adaptador de anulación Backbone.sync(method, model, options)
es posible con poca lógica adicional con la biblioteca contenedora de la base de datos.
Backbone.sync
esperan que el objeto de retorno sea el objeto jqXHR, que implementa Promise interface. Backbone.sync
se sobrescribe para intersectarse para el almacenamiento en caché en la base de datos del lado del cliente. Un proveedor de fuente de datos, $.db
, se establece un esquema correspondiente al modelo dado. (Véase la YDN-DB para más detalles.) Espero que el servidor back-end de Google acepta datos del modelo GData-como entrada (Atom), en el que cada modelo tiene atributo etag y resolución de conflictos optimistas se utiliza.
$.db = new ydn.db.Storage('db_name', schema);
var Backbone_sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
var df = $.Deferred();
if (method == 'read') {
var df_db = $.db.get(model.name, model.cid);
df_db.done(function(data) {
if (data) {
df.resolve(data);
options['header'].push({'If-Not-Match': data.etag});
var ajax_df = Backbone_sync(method, model, options);
ajax_df.done(function(new_data) {
if (new_data) {
assert(new_data.cid == model.cid);
$.db.put(model.name, new_data);
model.set(new_data).change();
} // else, no change
});
} else {
var ajax_df = Backbone_sync(method, model, options);
df.pipe(ajax_df);
ajax_df.done(function(new_data) {
$.db.put(model.name, new_data);
});
}
});
df_db.fail(function(e) {
throw e; // db connection blocking, or schema mismatch
});
} else if (method == 'update') {
options['header'].push({'If-Match': model.etag});
var ajax_df = Backbone_sync(method, model, options);
df.pipe(ajax_df);
ajax_df.done(function(new_data, status) {
if (status == 409) { // conflict
assert(new_data.cid == model.cid);
$.db.run(function(db) { // run in transaction
db.get(model.name, model.cid).done(function(data) { // NOTE: not $.db
if (data) {
var resolved_data = $.magic.resolve(new_data, data);
db.put(model.name, resolved_data);
model.set(resolved_data);
model.save(); // send merge result to server
} else {
db.put(model.name, new_data);
}
});
}, model.name, 'readwrite'); // transaction scope of model object store for read write operations
} else if (status == 404) { // not found
$db.clear(model.name, model.cid);
} else if (status < 300) {
assert(new_data.cid == model.cid);
$.db.put(model.name, new_data);
}
});
}
return df;
};
Los métodos restantes se pueden implementar de manera similar. Las colecciones y las consultas también pueden cruzarse y suministrarse desde la memoria caché de la base de datos.
Si el servidor no implementa etag, que queda trabajo, pero no te ahorrar ancho de banda del servidor, ni resolver los conflictos.
Muy interesante. Puede ser que la aplicación use IndexedDB directamente y permita que el derivador IndexedDB se sincronice con el servidor. Si hay algún conflicto, el contenedor debería enviar el evento actualizado. Esto simplificará cada rol. –
@KyawTun gracias, ¡esto parece un buen diseño! Pero cualquiera que sea el diseño que se me ocurra, necesitaría backbone.js para comunicarme con IndexedDB y el servidor remoto. Mi pregunta es ¿cuál de las dos formas mencionadas en mi post es la mejor manera de hacerlo. – shreyj