在写代码的时候突然发现一个请求重复请求了31次。这给我整不会了。
首先排查bug的可能原因:
- 认为其中的一些依赖的变量,在某些外部地方进行频繁的修改(因为Vue3 Ref响应式导出传递这个的可能行我认为是最大的, 这个方向帮我优化了一些其他问题,但是并不是造成这个bug的原因)。
- 依赖收集中的变量,它本身的属性被多次赋值。(后续思考了一下vue2源码响应式中对这个问题是由解决的,vue3不可能会出现错误。这个是错误的方向)
- 依赖收集的多个变量在本次watch中,是不是一直在被赋值。
最后发现,在这个watchEffect中有2个响应式变量每次都在修改。然后每次执行这个watchEffect的时候依赖收集到这2个变量上面。就会执行2次函数。然后这样就会出现重复执行bug。
贴一下这个bug的代码和优化后的代码
// 优化后的代码
// 依赖收集的响应式变量有companyList、companyBillCategory、companyAllBillCategory
// 在这份代码中限制了companyBillCategory、companyAllBillCategory的改变条件,让触发重复的情况减少
watchEffect(async () => {
if (companyList.value.length === 0) {
return;
}
// 这里因为获取了对象的数据所以进行了依赖收集
// 这是之前的问题代码。因为这里直接使用响应式变量的数据,所以后续companyBillCategoryTemp[item.companyId]每一次的赋值都是对响应式变量的修改触发watchEffect收集的函数导致这个函数会一直执行下去。billCategoryListTemp[it.id]这个也是同理。
// let companyBillCategoryTemp = companyBillCategory.value;
// let billCategoryListTemp = companyAllBillCategory.value;
//这里如果使用了结构,每次修改这个对象的一级属性的时候就不算是修改响应式变量了,就不会触发watchEffect
let companyBillCategoryTemp = {...companyBillCategory.value};
let billCategoryListTemp = {...companyAllBillCategory.value};
// 遍历用户公司列表 然后查看是否有新公司 然后获取公司的账单类型写入
for (let i = 0; i < companyList.value.length; i++) {
let item = companyList.value[i];
if (companyBillCategory.value[item.companyId]) {
continue;
}
// 依赖收集到这里就停止了,因为异步会让依赖收集停止
let billCategoryList = await getCompanyBillCategory(localStorage['id'], item.companyId);
companyBillCategoryTemp[item.companyId] = billCategoryList.categories.map(it => {
// 更新公司类型的时候同时更新全部类型的数据
let res = {
id: it.id,
name: it.name,
isOut: it.is_out
};
billCategoryListTemp[it.id] = res;
return res
})
}
if(Object.keys(companyBillCategoryTemp).length !== Object.keys(companyBillCategory.value).length) {
companyBillCategory.value = companyBillCategoryTemp;
}
if(Object.keys(billCategoryListTemp).length !== Object.keys(companyAllBillCategory.value).length) {
companyAllBillCategory.value = billCategoryListTemp;
}
})