使用fast-json-patch实现文档版本控制与时间线功能报错如何解决
问题根因
- 应用补丁的初始基准错误:生成diff补丁时的基准是包含
docnumber、notes空数组的初始state,但是应用补丁时使用了空对象{}作为初始值。生成的补丁都是针对/notes/xxx这类路径的修改操作,空对象没有notes属性,而JSON Patch规范(RFC 6902)要求操作路径的父级节点必须存在,fast-json-patch默认严格遵循该规范,不会自动创建不存在的父级路径,直接对/notes/下标路径执行add操作就会抛出赋值错误。 - 补丁缺失基础字段:因为初始state就包含
docnumber字段,所有编辑记录的diff补丁都不会包含新增docnumber的操作,从空对象应用补丁后,最终state也会丢失docnumber字段,不符合预期。
解决方法
1. 替换补丁应用的初始基准
把timetravel函数中初始化newDoc的代码从空对象改成和生成补丁时一致的初始state即可:
function timetravel(doc, editPoint) { if ( doc.parameters.currentedit === editPoint || editPoint > doc.parameters.edits || editPoint < 1 ) { return false; } const patchesToApply = doc.history.slice(0, editPoint); const patches = [].concat.apply([], patchesToApply); // 替换原来的 let newDoc = {} let newDoc = { docnumber: doc.parameters.docnumber, notes: [] }; newDoc = jsonpatch.applyPatch(newDoc, patches).newDocument; doc.state = newDoc; doc.parameters.currentedit = editPoint; return true; }
2. 补充初始化参数(可选优化)
在generateDoc的parameters初始化时补充currentedit字段,避免第一次调用timetravel时的undefined判断问题:
const doc = { // 新增currentedit默认值,刚生成的文档默认处于最新版本 parameters: { docnumber, edits, currentedit: edits }, history: [], state: { docnumber, notes: [] }, };
其他方案适配
你之前尝试的两种补丁应用方案逻辑本身没有问题,只要替换正确的初始基准对象都可以正常运行:
- 方案1把reduce的初始值从
{}替换为上述的初始state即可 - 方案2把
newDoc的初始值替换为上述的初始state即可
内容的提问来源于stack exchange,提问作者Dycey
相关产品推荐
相关产品推荐

