Ember.js 保存失败后如何恢复模型?

Ember.js 保存失败后如何恢复模型?,ember.js,ember-data,Ember.js,Ember Data,我们正在使用来处理表单中的数据。数据流通常是这样的:input->changeset->model->server->model->changeset->input。用户更改一些反映在变更集中并经过验证的输入。当用户按下submit时,变更集被烘焙到模型中,然后保存 这就是问题所在。若服务器拒绝接受更改,那个么我们将以模型处于损坏状态而告终。为了克服这个问题,我们实现了定制的save方法来模拟model.save的功能 基本思想是,如果我们只是保存一个模型,我们从变更集中获取变更并将其提交给服务

我们正在使用来处理表单中的数据。数据流通常是这样的:
input->changeset->model->server->model->changeset->input
。用户更改一些反映在变更集中并经过验证的输入。当用户按下
submit
时,变更集被烘焙到模型中,然后保存

这就是问题所在。若服务器拒绝接受更改,那个么我们将以模型处于损坏状态而告终。为了克服这个问题,我们实现了定制的
save
方法来模拟
model.save
的功能

基本思想是,如果我们只是保存一个模型,我们从变更集中获取变更并将其提交给服务器asi。如果失败了,那么基本上什么也不会发生。变更集保持不变,基础模型保持不变。但是,当保存成功时,我们使用从服务器返回的数据更新底层实体,方法与存储正常保存实体时所做的基本相同

这对属性和关系都很有效。唯一的问题是当我们需要检查在保存之后可能已经更改的关系时,因为它们会被延迟更新

任何帮助或想法都将不胜感激

/*
 * Saves an object by saving changes taken from a changeset.
 * Updates the target object if the operation succeeds.
 * @param changeset the changeset to save
 * @return {Promise} a promise that resolves to an object returned by the server
 */
saveChangeset(changeset) {
  const record = changeset.get('_content'); // not entirely a public field
  const id = record.get('id');
  const constructor = record.get('constructor');
  const modelName = constructor.modelName;

  const snapshot = changesetToSnapshot(changeset);
  const operation = record.get('isNew') ? 'createRecord' : 'updateRecord';

  record._internalModel.adapterWillCommit();
  return this.adapterFor(modelName)[operation](this, constructor, snapshot)
    .then(res => {
      // propagate the changes
      const model = this.modelFor(modelName);
      const serializer = this.serializerFor(modelName);
      const payload = serializer.normalizeResponse(this, model, res, id, operation);
      if (payload.included) {
        this.push({data: payload.included});
      }
      this.didSaveRecord(record._internalModel, {data: payload.data});
      changeset.rollback();
      return res;
    });
},


/**
 * Creates s snapshot-like object based on a changeset.
 */
export default function changesetToSnapshot(changeset) {
  const model = changeset.get('_content'); // not entirely a public field
  const isNew = model.get('isNew');
  const id = model.get('id');
  const constructor = model.get('constructor');
  const modelName = constructor.modelName;

  const changes = {};
  changeset.get('changes').forEach(change => {
    changes[change.key] = null; // The value does not matter
  });

  const filterByName = fn => (name, meta) => { // eslint-disable-line func-style
    if (name in changes) {
      fn(name, meta);
    }
  };

  const fieldFilter = isNew ? fn => fn : filterByName;

  return { // emulate a snapshot
    _isChangeset: true,
    type: constructor,
    record: model,
    modelName,
    id,
    eachAttribute: fn => model.eachAttribute(fieldFilter(fn)),
    eachRelationship: fn => model.eachRelationship(fieldFilter(fn)),
    attr: key => changeset.get(key),
    belongsTo(key, options) {
      assert('Snapshot from changeset can only return the id of a belongsTo relationship, not a snapshot of it', options && options.id);
      return get(changeset, key + '.id');
    },
    hasMany(key, options) {
      assert('Snapshot from changeset can only return the ids of a hasMany relationship, not an array of snapshots', options && options.ids);
      return changeset.get(key).map(e => e.get('id'));
    },
  };
}

请参见
DS.Model
class。我想这就是你想要的。遗憾的是,这种方法不会回滚关系。我还没有使用过很多与Ember的关系。但是,如果要更新的记录相对较少,则可以在将记录保存到存储之前创建该记录的副本。但是,如果请求失败,您可以再次获取副本并将其再次保存在存储中,而无需进行适配器调用。此外,您也可以尝试使用重新加载来重新蚀刻记录,但这并不理想。制作副本基本上是为了推动
重新加载关系
,而这并不是我目前正在努力实现的目标,我想知道你是否找到了解决问题的方法?