有个需求,需要循环某个数组,并在循环里调用某个方法,方法里有接口和处理逻辑
找了个示例
使用 foEach
// 模拟接口调用,延迟 num 秒后 打印 num
async say(num) {
console.log(num, 'begin:')
await new Promise(resolve => {
setTimeout(() => {
console.log(num)
resolve()
}, num * 1000)
})
},
//调用 foEach 循环的方法
forEach_Result() {
let nums = [2, 1]
nums.forEach(async n => {
await this.say(n)
})
},
结果为:
打印出来的结果与预期不符
。
。
。
原因:
网上搜了一下,发现,forEach 的内部调用简化后类似以下伪代码
while (index < arr.length) {
// 也就是我们传入的回调函数
callback(item,index)
}
forEach在遍历每个元素后,执行的是该方法接收的回调函数方法,然后在回调中,执行say()方法。forEach方法内部调用回调函数时,并没有使用 await 修饰,所以回调方法并不会等待上一个回调执行完毕。内部的 await 也就失去了意义。
解决:
使用 for of 循环 或者 for 循环
//for of
async for_of_Result() {
let nums = [2, 1]
for (let n of nums) {
await this.say(n)
}
},
//for
async for_Result() {
let nums = [2, 1]
for (let i = 0; i < nums.length; i++) {
await this.say(nums[i])
}
}
for of 和 for 循环的打印结果均为:
和预期相符