私に撮影を許可します。 backbone.jsを使ったことはありません。しかし、私は素晴らしいIndexedDBラッパーYDB-DBを持っており、私はbackbone.jsとangular.jsバインディングフレームワークをサポートする予定です。しかし、あまりそれはしないようです。
質問者が示唆しているように、データベースラッパーライブラリでは、追加のロジックをほとんど持たずに、オーバーライドするアダプタパターンはBackbone.sync(method, model, options)
で可能です。
Backbone.sync
戻りオブジェクトは、Promise interfaceを実装するjqXHRオブジェクトであると想定します。 Backbone.sync
は、クライアント側のデータベースでキャッシュするために交差するようにオーバーライドされます。データソースプロバイダ$.db
には、指定されたモデルに対応するスキーマが設定されます。私は、バックエンドサーバがGoogle GDataのようなモデルデータ(Atom Entry)を受け入れることを期待しています。各モデルにはetag属性があり、楽観的な競合解消が使用されています。
$.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;
};
同様の方法で残りのメソッドを実装できます。コレクションと問合せは、データベース・キャッシュと交差してデータベース・キャッシュからも供給できます。
サーバーがetagを実装していない場合でも動作しますが、サーバーの帯域幅を節約したり、競合を解決したりすることはありません。
非常に興味深い。アプリケーションでIndexedDBを直接使用し、IndexedDBラッパーをサーバーに同期させることができます。競合が発生した場合、ラッパーは更新されたイベントをディスパッチする必要があります。これにより、それぞれの役割が単純化されます。 –
@KyawTunありがとう、これは良いデザインのようです!しかし、どのような設計であっても、IndexedDBとリモートサーバーの両方と通信するためにbackbone.jsが必要です。私の質問は、私のポストで言及されている2つの方法のどちらが良い方法であるかです。 – shreyj