转载:为啥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