2012-10-04 5 views
6

私はオフライン対応のWebアプリケーションで作業しています。クライアントコードにBackbone.jsを使用しています。ユーザーのオンライン/オフライン状態に応じて、リモートサーバーとローカルのIndexedDBを切り替えるにはbackbone.jsが必要です。これを行う正しい方法は次のどれですか:IndexedDBとBackbone.jsを使用したリモートサーバの使用

  1. これをスーパーフィードで使用してください。しかし、私はそれがオフラインストレージだけでなく、オフラインとオンラインの両方に対応していると感じています。
  2. backbone.jsでsync()メソッドをオーバーライドし、独自のニーズに合わせたアダプタを作成します。
+0

非常に興味深い。アプリケーションでIndexedDBを直接使用し、IndexedDBラッパーをサーバーに同期させることができます。競合が発生した場合、ラッパーは更新されたイベントをディスパッチする必要があります。これにより、それぞれの役割が単純化されます。 –

+0

@KyawTunありがとう、これは良いデザインのようです!しかし、どのような設計であっても、IndexedDBとリモートサーバーの両方と通信するためにbackbone.jsが必要です。私の質問は、私のポストで言及されている2つの方法のどちらが良い方法であるかです。 – shreyj

答えて

5

私に撮影を許可します。 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を実装していない場合でも動作しますが、サーバーの帯域幅を節約したり、競合を解決したりすることはありません。

関連する問題