数组的异步循环遍历方法 - Luomusha/blog GitHub Wiki

数组的异步循环便利方法

普通遍历

如果说,请写出遍历数组的方法,大多数前端不屑一顾的列举

const array = [1,2,3,4,5,6,7,8];
array.forEach((num:number) => {
    console.log(num)
})


const array = [1,2,3,4,5,6,7,8];
for(let i=0;i<array.length;i++){
    console.log(array[i])
}

异步遍历

但是如果循环项是异步的呢? 比如有一个url列表,要求遍历列表,依次请求数据,累加响应的字符串长度?

const urlList = [
    "https://www.baidu.com",
    "https://www.sina.com",
    "https://www.qq.com",
    "https://www.bing.com",
]


const countString = async (url:string):Promise<number> => {
    const res = await fetch(url)
    const resData = await res.text();
    return resData.length
}

给30秒考虑

...

让我们先想当然的套用一下上面的方法试试?

let count = 0
urlList.forEach(async (url:string) => {
    console.log("start")
    count += await countString(url)
    console.log("end", count)
});

结果为:

start
start
start
start
end 227
end 102012
end 488005
end 111462

从结果上看没什么问题。 但是我们仔细观察后发现,程序是一次性发送所有请求,不管响应如何的。 如果同时有成百上千的请求同时发送,就会大量占用内存,造成电脑卡司。

所以能不能有办法依次发送请求,等上一个请求响应后再发送第二个呢? 思考三十秒

递归

直接上答案:递归。

递归应该是变成里面最复杂的逻辑之一。大家要注意递归和遍历的区别,体会递归和遍历的区别。 过程略,直接上代码

let count = 0
let index = 0;
const countOneByOne = async (index:number) =>{
    console.log("start")
    const url = urlList[index];
    count += await countString(url)
    console.log("end", count)

    if(index + 1 < urlList.length){
        await countOneByOne(index + 1)
    }
};
countOneByOne(0)

结果如下:


start
end 227
start
end 488233
start
end 590217
start
end 701648

for await (value of array)

递归太难了。有没有简单的办法呢? 有!

请出我们的主角,上代码

let count = 0;
const countAsync = async () => {
    for await (const url of urlList) {
        console.log("start")
        count += await countString(url)
        console.log("end", count)
    }
}
countAsync()

结果如下:


start
end 227
start
end 488242
start
end 590226
start
end 701688
⚠️ **GitHub.com Fallback** ⚠️