转载:为啥await在forEach中不生效?-腾讯云开发者社区-腾讯云 (tencent.com)
两天要写循环遍历请求接口,于是就在forEach中用到了await,但是根本不是我想要的啊!
于是各种查,各种搜,终于有点明白了。先看段代码:
function test(){
let arr =[3,2,1]
arr.forEach(async item=>{
const res = await fetch(item)
console.log("end")
})
}
function fetch(x){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
revolve(x)
}, 500*x)
})
}
test();
期望打印出来顺序是:
3
2
1
end
然而打印顺序却是:
end
1
2
3
原因是forEach只支持同步代码
Pollyfill版本的forEach,简化以后类似于下面的伪代码:
while(index < arr.length){
callback(item, index)
}
解决办法
方法一:Promise.all
async function test(){
let arr = [3,2,1]
await Promise.all(arr.map(async item=>{
const res = await fetch(item);
console.log(res)
}))
console.log("end")
}
async函数肯定会返回一个Promise对象,map返回一个存放Promise的数组。但是这样并不能保证fetch是按顺序完成的,如果想按顺序,请用下面的方法。
方法二:for ... of
async function test(){
let arr =[3,2,1];
for(const item of arr){
const res = await fetch(item);
console.log (res)
}
console.log("end")
}
function fetch(x){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(x)
}, 1500*x)
})
}
test();
因为for... of和forEach内部的机制不同,forEach是直接调用回调函数,for...of 是通过迭代器的方式去遍历的:
async function test(){
let arr = [3,2,1];
const iterator = arr[Symbol.iterator]()
let res = iterator.next()
while(!res.done){
const value = res.value;
const res1 = await fetch(value);
console.log(res1);
res.iterator.next();
}
console.log("end")
}
以上代码等价于for...of
参考文章:https://yuchengkai.cn/blog/2019-04-01.html#%E6%80%8E%E4%B9%88%E8%A7%A3%E5%86%B3%EF%BC%9F