sto*_*fln 5 javascript mobx mobx-state-tree
我正在编写一个电子应用程序,并将所有应用程序数据保存在一个 MST 树中。现在我注意到,时不时地您会遇到数据变得不一致的情况(缺少引用对象等)。虽然任何类型的数据库都可能发生这种情况,但我发现 MST 存在一个特殊问题:
由于我们有一棵树在应用程序启动时被反序列化,然后用作单个快照,因此单个不一致将导致整个应用程序失败。我的应用程序将无法获得任何数据。
关于如何处理这个问题有任何提示吗?
更多信息
目前,每次树发生变化时(onSnapshot),我都会创建一个快照并将其保存在 localStorage 中。因此,错误用例是:创建 mst 对象 -> 在树的其他部分创建引用 -> 删除 mst 对象 -> 触发 onSnapshot -> 损坏的树被持久化。重新加载应用程序不会有帮助,因为树持续处于损坏状态。
为了避免传入数据不一致,我在模型中添加了默认值。例如
const collectionModel = types.model({
type: types.optional(types.literal('collections'), 'collections'),
preview: types.optional(
types.model({
products: types.array(SelectableProduct)
}),
{}
),
data: types.optional(types.model({
items: 24,
perRow: 4,
global: types.optional(EvergreenQuery, {}),
curated: types.array(EvergreenItemSettings)
}), {})
})
Run Code Online (Sandbox Code Playgroud)
collectionModel这将允许我从空对象创建一个实例
collection1 = collectionModel.create({})
Run Code Online (Sandbox Code Playgroud)
当您使用引用时,请确保使用safeReference
来自文档
* `types.safeReference` - A safe reference is like a standard reference, except that it accepts the undefined value by default
* and automatically sets itself to undefined (when the parent is a model) / removes itself from arrays and maps
* when the reference it is pointing to gets detached/destroyed.
*
* Strictly speaking it is a `types.maybe(types.reference(X))` with a customized `onInvalidate` option.
Run Code Online (Sandbox Code Playgroud)
因此,如果您要删除存储中其他位置引用的节点,则该引用将设置为未定义。根据我的经验,损坏的引用特别难以调试。
我喜欢 mobx-state-tree 迫使我有一个明确的结构。这让我在编写逻辑之前先考虑一下结构,从而简化了逻辑的编写。
您可以做的一个技巧是在保存快照之前实例化一个新模型。如果成功则保存快照,如果不成功则跳过它。
const MyModel = types.model({})
onSnapshot(myModelInstance, s => {
try {
const testModel = MyModel.create(s)
if (localStorage) {
// here you can save the snapshot because you know for sure it won't break
localStorage.setItem('snap', JSON.stringify(s))
}
} catch(e) {
// log or something
// OR
console.log(
'snapshot failed because of',
difference(s, JSON.parse(localStorage.getItem('snap'))
)
}
})
// this methos does a deep difference between two objects
export const difference = <T>(orObject: object, orBase: object): T => {
function changes(object: any, base: any): any {
return _.transform(object, function(
result: any,
value: any,
key: any
): any {
if (!_.isEqual(value, base[key])) {
result[key] =
_.isObject(value) && _.isObject(base[key])
? changes(value, base[key])
: value;
}
});
}
return changes(orObject, orBase);
};
Run Code Online (Sandbox Code Playgroud)
diff 方法非常有用,因为它可以更轻松地找出崩溃的原因。这样,localStorage 将只有有效的快照,任何无效的快照都会记录问题的原因。
小智 1
反序列化的数据来自哪里?我对 Electron 不太熟悉,但我想您在应用程序会话之间将其存储在本地(通过快照 mst 树)。
我的第一个预感是看看当你序列化它时会发生什么?也许在保存快照之前验证快照是个好主意(我想在应用程序关闭时?)?
这种不一致是否“一致”?我的意思是 - 是树的同一部分引起的吗?也许拆分树 - 序列化 -> 反序列化不同部分的多个快照,而不是 1 个大的东西。
虽然我确实使用mst,但我不使用快照,至少不使用整个树级别,检查创建快照时树是否被冻结..也许,我认为不太可能,在快照时仍然在树上进行更改正在编写中。
| 归档时间: |
|
| 查看次数: |
3073 次 |
| 最近记录: |