1、问题现象
打开待办报错:“Cannot read properties of undefined (reading 'appApproveSetDTOS')”
2、问题复现
- 首先,询问用户操作路径,以及查看用户出现问题的现象,在测试及线上尝试复现出问题;
- 查看用户报错的具体原因,后端接口未报错,但返回数据有缺失;前端报错开发无法定位原因;
- 分析数据库数据,发现发起两条审批,但实际用户收到3条待办,且有一个表单提交,却有两条审批数据app_authorization_approve_v2 及两条待办,时间间隔3s左右。
- 初步断定,是因为某些原因导致提交审批时重复引起,于是在弱网或快速点击的情况下,多次操作复现此问题,复现出来。
3、原因分析
(1)表单授权,第一步,配置授权人员,触发接口appAuthorizeAndApproveConfig,在表app_authorization_v2生成一条数据
(2)第二步,提交审批生成approveid,并填充到上一步的数据中【提交审批时,携带的authorizationIds会去app_authorization_v2中找id符合authorizationIds的数据,然后更新approveId】;同时生成待办数据发到审批人
(3)发现问题,当触发多次提交审批时,会生成多个approveid,同时生成多条待办数据,但第一步生成的数据只有一条,approveid一直更新,最后一个approveid覆盖到这条数据中。
当待办中根据approveid查待办详情数据时,只有最后一个待办才能查到,其他的都查不到,所以打开待办页面空白报错。
原因:多次提交时,后提交的数据在app_authorization_v2表更新approveid值,所以先提交的数据的approveId已经找不到对应的数据
总结:解决点击提交审批时多次提交的问题就可以了,因为提交审批时多次提交,导致前一条的数据的approveId查不到对应数据
4、解决方案1前端控制
与前后端开发沟通后,决定采用“前端防抖与Loading限制”,防止接口重复调用
一、防抖(Debounce)的作用
基本原理
防抖是一种延迟执行技术,它会将多次连续调用合并为一次调用,只有在指定的时间间隔内没有新调用时才会真正执行。
在防止接口重复调用中的作用:
(1)高频操作合并:将短时间内多次触发的事件合并为一次执行
(2)减少无效请求:例如搜索框输入时,只在用户停止输入300ms后才发起请求,而不是每输入一个字符就请求一次
(3)防止快速连续点击:按钮防抖可以避免用户快速多次点击导致的重复提交
适用场景:
搜索框实时搜索建议
窗口resize事件处理
按钮防重复点击(需配合视觉反馈)
局限性:
不能完全阻止刻意快速操作
防抖期间用户看不到任何反馈,可能误以为操作未生效
二、Loading限制的作用
基本原理
通过加载状态锁定界面,在请求完成前阻止用户继续操作。
在防止接口重复调用中的作用:
1、视觉+逻辑双重锁定:
2、明确的用户反馈:通过加载动画让用户明确知道操作已接受,正在处理中
3、完整的请求周期控制:从点击到响应返回全程锁定,比单纯防抖更可靠
适用场景:
表单提交
重要操作确认(支付、删除等)
需要明确反馈的异步操作
优势:
提供更好的用户体验
能有效防止请求发出后的重复操作
实现简单直接
三、结合后的效果:
防抖处理短时间内多次点击
Loading状态防止防抖期间的新操作
请求发出后Loading防止重复提交
提供清晰的用户反馈
四、对比总结
对于关键业务接口,建议同时使用两种方案:防抖处理初始阶段的快速操作,Loading确保请求过程中的状态控制
5、解决方案2后端控制
逻辑控制
因为审批中的数据只有一条,故控制待办也只能产生一条,这样就不会有查不到approveId的情况了。
这种方案可从根本原因中控制住数据出错。
6、实际效果
经过团队讨论,前端进行了控制即可,测试进行了快速点击、弱网操作、以及调用接口并发等方式进行了验证,重复调用的情况确实得到了比较好的控制。
由于测试跟踪需求及线上问题比较多,考虑到此块功能,多次出现问题,之前在多处也进行了loading限制,但问题未根本解决。
此次防抖限制,是否能彻底解决问题?
实际情况也是,测试环境未出现异常待办,但线上测试账号仍出现了。
既然知道后端逻辑可控制,为何不加双重保险?
最终决定,前端两端都做改进,最终观察一段时间,发现问题得以彻底解决。