最近写项目的时候,碰到个问题:
请求的数组中某个字段需要执行请求进行二次渲染,在遍历原数组执行异步请求的时候,碰到了两个问题,第二个问题是因为第一个问题解决之后出现的新问题。。。。
第一个问题:数组遍历执行异步请求后通过push到新数组导致顺序可能会发生改变
image.png
第二个问题:循环遍历未结束时,新数组就已经赋值给原数组了,导致控制台报某个字段undefined
解决第一个问题的办法:
在循环原数组进行遍历的时候,可以携带索引,然后将请求结果赋值新数组的时候按照索引进行插入,这样新数组顺序跟原数组顺序就是一样的了
再通过索引改变新数组的时候可能存在个问题:
Vue官网上的:
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
2.当你修改数组的长度时,例如:vm.items.length = newLength
为了解决第一类问题,以下两种方式都可以实现和vm.items[indexOfItem] = newValue
相同的效果,同时也将在响应式系统内触发状态更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
你也可以使用 vm.$set
实例方法,该方法是全局方法 Vue.set
的一个别名:
vm.$set(vm.items, indexOfItem, newValue)
第二个问题:因为js是单线程,执行遍历的时候下面的赋值操作可能就已经结束了,然后新数组在遍历完成之前都是空数组,这才导致了某个字段取不到。
解决办法:在执行遍历前声明一个索引,每执行一次遍历结束索引加1,如果索引等于原数组长度,说明执行完成,此时在进行赋值即可
private getDataSourceFilter(dataSource: ResourceInfo[]) {
let newDataSource: ResourceInfo[] = [];
let idx = 0;
dataSource.forEach(async (item: ResourceInfo, index: number) => {
let areaName = "";
const PromiseAll = [
HttpRequest.getAreaInfoById({ areaId: item.cityId }),
HttpRequest.getAreaInfoById({ areaId: item.countyId })
];
const resAll = await Promise.all(PromiseAll);
if (resAll) {
resAll.forEach((resItem: any) => {
if (resItem && resItem.data) {
areaName += resItem.data.areaName;
} else {
areaName += "";
}
});
const newItem = Object.assign(item, { areaName });
// newDataSource.push(newItem);
/**
* Vue.set
*/
Vue.set(newDataSource, index, newItem);
idx += 1;
if (dataSource.length === idx) {
this.dataSource = newDataSource;
this.loading = false;
}
}
});
网友评论