js实现并发请求网络控制

1,521 阅读1分钟

实现一个批量请求函数 multiRequest(urls, maxNum),要求如下:

  • 要求最大并发数 maxNum
  • 每当有一个请求返回,就留下一个空位,可以增加新的请求
  • 所有请求完成后,结果按照 urls 里面的顺序依次打出。

实现思路:递归进行实现,最初发送请求次数为最大并发上限,等某个请求结果返回后递归进行调用run方法发送请求,并使用新数组存放返回的请求结果,当所有请求都执行过之后,不再进行请求,等所有结果返回后,执行resolve方法,代码如下:

function multiRequest(tasks, maxNum) {
    const len = tasks.length;

    // 创建新数组用于存放请求的返回结果
    const result = new Array(len).fill(false);

    // 请求执行次数
    let count = 0;
    return new Promise((resolve, reject) => {

        // 当小于最大并发数时,执行请求
        while(count < maxNum) {
            run();
        }
        function run() {
            let cur = count++;
            tasks[cur]().then(res => {
                result[cur] = res;
            }).catch(err => {
                result[cur] = err;
            }).finally(() => {

                // 某个请求结果返回后,判断是否需要执行新的请求
                if(count < tasks.length) {
                    run();
                } else if (!result.includes(false)) {

                    // 所有的请求执行完成
                    resolve(result);
                }
            })
        }
    });
}

以下示例模拟请求操作:

function task1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("task1");
            console.log("task1")
        })
    });
}
function task2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("task2");
            console.log("task2")
        }, 1000);
    });
}
function task3() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("task3");
            console.log("task3")
        }, 20);
    });
}
function task4() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("task4");
            console.log("task4")
        }, 500);
    });
}
const tasks = [task1, task2, task3, task4];

// 执行
multiRequest(tasks, 2).then(res => {console.log(res)});

执行结果如下:

image.png