You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
在开发 web 应用程序时,性能都是必不可少的话题。同时通用 web 应用程序离不开数据的增删改查,虽然用户大部分操作都是在查询,但是我们也不可以忽略更改数据对于系统的影响。于是个人写了一个业务数据比对库 diff-helper。方便开发者在前端提交数据到服务端时候去除不必要的信息,优化网络传输和服务端性能。
// 添加异常错误抛出constinvariant=(condition: boolean,errorMsg: string)=>{if(condition){thrownewError(errorMsg);}};// 判断是否是真实的对象constisRealObject=(val: any): val is Record<string,any>=>{returnObject.prototype.toString.call(val)==="[object Object]";};simpleObjDiff=({
newVal,
oldVal,
options,}: SimpleObjDiffParams): Record<string,any>=>{// 添加错误传参处理invariant(!isRealObject(newVal),"params newVal must be a Object");invariant(!isRealObject(oldVal),"params oldVal must be a Object");// ...const{ diffFun, empty }={ ...DEFAULT_OPTIONS, ...options};// ...Object.keys(oldVal).forEach((key)=>{// 如果已经检查过了,直接返回if(checkedKeys.has(key)){return;}// 设定空数据,建议使用 null 或 空字符串diffResult[key]=empty;});};
在开发 web 应用程序时,性能都是必不可少的话题。同时通用 web 应用程序离不开数据的增删改查,虽然用户大部分操作都是在查询,但是我们也不可以忽略更改数据对于系统的影响。于是个人写了一个业务数据比对库 diff-helper。方便开发者在前端提交数据到服务端时候去除不必要的信息,优化网络传输和服务端性能。
项目演进
任何项目都不是一触而就的,下面是关于 diff-helper 库的编写思路。希望能对大家有一些帮助。
简单对象比对
前端提交 JSON 对象数据时,很多情况下都是对象一层数据比对。在不考虑对象中还有复杂数据(嵌套对象和数组)的情况下,编写如下代码
此时我们就可以使用该函数进行一系列简单数据操作了。
添加复杂属性比对
当前函数在面对对象内部有复杂类型时候就没办法判断了,即使没有更改的情况下,结果也会包含新数据属性,但是考虑到提交到服务端的表单数据一般不需要增量提交,所以这里试一试 JSON.stringify 。
诸如:
对比上述结果,我们可以看到,JSON.stringify 如果不提供 replacer 可能会对对象类型数据的生成结果产生“误伤”。但从系统实际运行上来说,对象内部属性不太会出现排序变化的情况。直接进行以下改造:
这时候尝试一下复杂数据类型
添加自定义对象属性比对
如果只使用 JSON.stringify 话,函数就没有办法灵活的处理各种需求,所以笔者开始追加函数让用户自行适配。
此时我们尝试传入 diffFun 来看看效果:
通过 diffFun 函数,开发者不但可以自定义属性处理,还可以利用 fast-json-stringify 来优化内部属性处理。该库通过 JSON schema 预先告知对象内部的属性类型,在提前知道数据类型的情况下,针对性处理会让 fast-json-stringify 性能非常高。
可以看到,利用 fast-json-stringify 同时无需考虑对象属性的内部顺序。
添加其他处理
这时候开始处理其他问题:
简单对象比对函数就基本完成了。有兴趣的同学也可以直接阅读 obj-diff 源码 。
简单数组对比
接下来就开始处理数组了,数组的比对核心在于数据的主键识别。代码如下:
此时我们就可以使用该函数进行一系列简单数据操作了。
函数到这里就差不多可用了,我们可以传入参数然后拿到比对好的结果发送给服务端进行处理。
添加默认对比函数
这里就不传递 getChangedItem 的逻辑,函数将做如下处理。如此我们就可以不传递 getChangedItem 函数了。
添加排序功能
部分表单提交不仅仅只需要增删改,还有排序功能。这样的话即使用户没有进行过增删改,也是有可能修改顺序的。此时我们在数据中添加序号,做如下改造:
开始测试一下:
简单数组比对函数就基本完成了。有兴趣的同学也可以直接阅读 list-diff 源码 。
以上所有代码都在 diff-helper 中,针对复杂的服务端数据请求,可以通过传参使得两个函数能够嵌套处理。同时也欢迎大家提出 issue 和 pr。
其他
针对形形色色需求,上述两种函数处理方案也是不够用的,我们来看看其他的对比方案。
数据递归比对
当前库也提供了一个对象或者数组的比对函数 commonDiff。可以嵌套的比对函数,可以看一下实际效果。
westore 比对函数
westore 是个人使用过最好用的小程序工具,兼顾了性能和可用性。其中最为核心的则是它的比对函数,完美的解决了小程序 setData 时为了性能需要建立复杂字符串的问题。
以下代码是实际的业务代码中出现的:
这里就不介绍 westore 的用法了,直接看一下 westore diff 的参数以及结果:
不过这种增量比对不适合通用场景,大家有需求可以自行查阅代码。笔者也在考虑上面两个比对函数是否有其他的使用场景。
参考资料
fast-json-stringify
westore
diff-helper
The text was updated successfully, but these errors were encountered: