您的位置:首页 > 前端开发 > 技术笔记

javascript for循环执行异步请求(顺序执行、并发限定数量执行)

2018-11-05 11:38:37

需求
有一userid数组和异步方法getUserInfo(userid),遍历数组将用户信息获取下来。
let userids = [1001,1002,1003,1004,1005…];


1、for/forEach循环

for(let i=0;i<userids.length;i++){
    getUserInfo(userids[i]).then(msg=>{
        console.log(msg);
    })
}
//forEach
userids.forEach(item=>{
    getUserInfo(userids[i]).then(msg=>{
        console.log(msg);
    })
})

优点:总请求时间短。
缺点:无法保证请求成功的顺序,且userids数组长度不宜过长。
此类遍历,实际是瞬间同时并发数组长度的请求,由于是均是异步,故无法保障数据返回的先后顺序。且如果数组长度过长,并发过多,会有性能问题,容易造成浏览器卡死。


2、for of / for in循环

//for of
async fetchData(){
    for(let val of userids){
        let msg = await getUserInfo(val);
        console.log(msg);
    }
}
//for in
async fetchData(){
    for(let x in userids){
        let msg = await getUserInfo(userids[x]);
        console.log(msg);
    }
}
//调用
fetchData();

优点:可以保证按照数组顺序请求。
缺点:总请求时间长。
由于是顺序执行,没有并发,即前一个请求完成才会开始下一个请求,所以请求时间累积,时间过长。

3、一次并发指定数量的请求

//切割数组,生成新的数组,如[[1001,1002,1003],[1004,1005,1006]...]
function cutAry(ary,step){
    let newAry = [];
    let l = Math.ceil(ary.length/step);
    for(let i=0;i<l;i++){
        let start = step * i;
        let end = start + step;
        newAry.push(ary.slice(start,end));
    }
    return newAry;
}
//遍历切割后的数组,每一组同时并发3次请求
async fetchData(){
    let arys = cutAry(userids,3);
    for(let ids of arys){
        //将每一组请求生成的promise对象存入一个数组,
        let promiseAry = ids.map(item=>{
            return getUserInfo(item);
        });
        //Promise.all方法来保证所有请求已完成,并将结果集存入变量results
        let results = await Promise.all(promiseAry);
        results.forEach(v=>console.log(v));
    }
}
//调用
fetchData();

优点:可以保证请求成功的顺序,也可以一次性并发指定数量的请求。
缺点:须浏览器支持es6,不过,可以采用现有的promise库如q.js进行改进上述方法来解决这个问题。

more 最近