Promise下的同步遍历和异步遍历的不同方法

863 阅读1分钟

有时候,我们有一个返回值为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也是同样的异步函数。

解决方案

  1. for...of
async function test(){
    for(let num of nums){
        let res1 = await multi(num)
        console.log(res1)
    }
}
test()
  1. for...in
async function test(){
    for(let num in nums){
        let res2 = await multi(num)
        console.log(res2)
    }
}
test()
  1. for(){}
async function test(){
    for(let i = 0; i < nums.length; i++){
        let res3 = await multi(num[i])
        console.log(res3)
    }
}
test()
  1. while() {}
async function test(){
    let len = nums.length
    while(len--){
        let res4 = await multi(len)
        console.log(res4)
    }
}
test()
  1. promise.all
async function test(){
    Promise.all(nums.map(async num=>{
        return await multi(num)
    })).then(res => {
        console.log(res)
    })
}
test()