JS在循环中(for,forEach,map)调用异步代码问题,以及分别中途停止(for,forEach,map)循环的方法
最开始的错误代码:
handelPipeline() {
let arr = [];
this.tableData.forEach(async (item, index) => {
if (item.itemCode == 'DXGX_XZ') {
if (item.children) {
item.children.forEach(async (item, index) => {
let { data, isError } = await getTest({ analysisTypeCode: item.itemCode });
arr.push({ ...item, isIntersect: data.isIntersect, shape: data.shape });
});
}
}
});
this.tableData.forEach(async (item, index) => {
if (item.itemCode == 'DXGX_XZ') {
if (item.children.length) {
this.childrenArr = item.children;
this.$set(item, 'children', arr);
}
}
});
this.tableData.forEach((item, index) => {
if (item.itemCode == 'DXGX_XZ') {
this.childrenArr = item.children;
}
});
},
这样的话会造成最后的this.childrenArr 的值是空的,并没有赋值上去,当时不知道,后来才发现如果在循环中异步代码的时候,用forEach和map的话,即使写了await,但是也不会进行等待的效果,所以才会出现上述this.childrenArr虽然写在最下面,但是还是没有被复值的问题,
###解决方法
1.换成for循环,因为用for循环的时候会受await的影响,直到接收到数据才会进行下一步
async handelPipeline() {
let arr = [];
for (let index = 0; index < this.tableData.length; index++) {
if (this.tableData[index].itemCode == 'DXGX_XZ' && this.tableData[index].children) {
for (let i = 0; i < this.tableData[index].children.length; i++) {
let { data, isError } = await getTest({ analysisTypeCode: this.tableData[index].children[i].itemCode });
arr.push({ ...this.tableData[index].children[i], isIntersect: data.isIntersect, shape: data.shape });
}
}
}
this.tableData.forEach(item => {
if (item.itemCode == 'DXGX_XZ' && item.children.length) {
this.$set(item, 'children', arr);
}
});
this.tableData.forEach(item => {
if (item.itemCode == 'DXGX_XZ') {
this.isPipeline = item.children.some(res => res.isIntersect === 0);
}
});
if (this.isPipeline) {
// 更新管线大类
this.tableData.forEach((items, index) => {
if (items.itemCode == 'DXGX_XZ') {
this.tableData[index].isIntersect = 0;
}
});
}
},
2.用Promise all
与传统的 for 循环相比,用 Promise.all 可以有效的提升性能。因为 await 等待的是所有的 Promise 执行完毕的结果,即锁住的是 Promise.all,而内部的 map或forEach 依旧是同步执行的。所以对于循环体内的异步函数来说,它不需要等待上一个迭代完成,再去执行下一个迭代——await 这个语法糖会等待 Promise 执行完毕再去执行下一个 Promise。
async handlePipeline() {
let arr = [];
await Promise.all(this.tableData.map(async (item) => {
if (item.itemCode == 'DXGX_XZ' && item.children) {
await Promise.all(item.children.map(async (child) => {
let { data, isError } = await getTest({ analysisTypeCode: child.itemCode });
arr.push({ ...child, isIntersect: data.isIntersect, shape: data.shape });
}));
}
}));
this.tableData.forEach((item) => {
if (item.itemCode == 'DXGX_XZ' && item.children.length) {
this.childrenArr = item.children;
this.$set(item, 'children', arr);
}
});
this.tableData.forEach((item) => {
if (item.itemCode == 'DXGX_XZ') {
this.childrenArr = item.children;
}
});
}
注意!!!如果在循环里面涉及到异步操作,如果为了方便省事,就直接换for,反正我最后还是直接用的for哈哈哈
拓展!!!
在(for,forEach,map)循环中,如果想中途停止的话,在for循环里面可以直接用break,但是在forEach和map,用break和return是没用的,我自己都试过,要在满足条件的地方抛掷一个错误,就好了
const arr = [1, 2, 3, 4, 5, 6, 7];
try {
arr.forEach((element) => {
console.log(element);
if (element === 3) {
throw '终止'; // 抛出自定义异常
}
});
} catch (e) {
}