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的关系。但是,如果要更新的记录相对较少,则可以在将记录保存到存储之前创建该记录的副本。但是,如果请求失败,您可以再次获取副本并将其再次保存在存储中,而无需进行适配器调用。此外,您也可以尝试使用重新加载来重新蚀刻记录,但这并不理想。制作副本基本上是为了推动重新加载关系
,而这并不是我目前正在努力实现的目标,我想知道你是否找到了解决问题的方法?