使用IndexedDB以及Backbone.js的远程服务器

时间:2012-10-04 07:33:10

标签: backbone.js indexeddb

我正在开发支持离线功能的网络应用。我使用Backbone.js作为客户端代码。我需要backbone.js根据用户的在线/离线状态在远程服务器和本地IndexedDB之间切换。以下哪种方法是正确的方法:

  1. superfeedr使用此indexeddb-backbone adapter。但我觉得它更多地适用于离线存储,而不是离线和在线。
  2. 覆盖backbone.js中的sync()方法,从而创建自己需要的特定适配器。

1 个答案:

答案 0 :(得分:5)

让我拍一张照片。我从来没有使用backbone.js。但是,我有很棒的IndexedDB包装器YDB-DB,我计划支持backbone.js和angular.js绑定框架。但似乎没什么可做的。

正如提问者建议的那样,覆盖Backbone.sync(method, model, options)的适配器模式是可能的,而数据库包装器库的附加逻辑很少。

Backbone.sync期望返回对象是jqXHR对象,它实现Promise interfaceBackbone.sync被覆盖以交叉在客户端数据库中进行缓存。数据源提供程序$.db设置与给定模型对应的模式。 (有关更多详细信息,请参阅YDN-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,它仍然有效,但您不会节省服务器带宽,也不会解决冲突。