有时候,我们有一个返回值为promise的方法,需要在循环遍历中使用,但是按照事件执行顺序,该方法会异步执行,比如:
function multi(num) {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(num*num)
}, 1000)
})
}
const nums = [1, 2, 3]
使用foreach来遍历:
nums.forEach(async (num)=>{
const res = await multi(num)
console.log(res)
})
console.log('next')
打印结果是:
next 1 4 9
因为这是一个异步执行,所以next先打印。
并且,是在一秒后,三个相继出现,并不是我们想要的效果:一秒打印一个答案。
这是因为:await需要等待promise返回成功的结果后再执行,但是因为定时器,multi函数在返回结果之前,foreach已经遍历完了,所以会在1000s后,等计时器结束,执行await后的内容。
map也是同样的异步函数。
解决方案
- for...of
async function test(){
for(let num of nums){
let res1 = await multi(num)
console.log(res1)
}
}
test()
- for...in
async function test(){
for(let num in nums){
let res2 = await multi(num)
console.log(res2)
}
}
test()
- for(){}
async function test(){
for(let i = 0; i < nums.length; i++){
let res3 = await multi(num[i])
console.log(res3)
}
}
test()
- while() {}
async function test(){
let len = nums.length
while(len--){
let res4 = await multi(len)
console.log(res4)
}
}
test()
- promise.all
async function test(){
Promise.all(nums.map(async num=>{
return await multi(num)
})).then(res => {
console.log(res)
})
}
test()