【面试】常见面试题--并发请求限制

75 阅读1分钟

题目

实现一个并发请求函数concurrencyRequest(urls, maxNum),要求如下:

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

思路

  1. 函数返回一个promise
  2. maxNum要判断,取urls数组的length和maxNum的最小值
  3. count计算请求结果数量,如果count === len,则resolve结果
  4. index保存当前发出请求的序号,用来记录结果的序列

代码

function concurrencyRequest(urls, maxNum) {
    return new Promise((resolve, reject) => {
        const len = urls.length;
        maxNum = Math.min(len, maxNum);
        let result = [];
        let count = 0; // 记录结果完成的数量
        let index = 0; // 记录请求结果的index,两个是不一样的,需要区分开
        const run = async () => {
            url = urls.shift();
            console.log('url', url);
            if (!url) {
                return;
            }
            let cur = index++;
            try {
                const res = await fetch(url);
                result[cur] = res;
            } catch (err) {
                result[cur] = err;
            }
            count++;
            run();
            if (count === len) {
                resolve(result);
            }
        }
        for (let i = 0; i < maxNum; i++) {
            run();
        }
    });
}

const urls = [];
for (let i = 1; i <= 20; i++) {
    urls.push(`https://jsonplaceholder.typicode.com/todos/${i}`);
}
concurrencyRequest(urls, 3)
    .then(res => console.log('final', res));

结果如下:

image.png

image.png

关于前端:如何实现并发请求数量控制?

再来一个demo😂

const request = (delay, id) => {
    return function() {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log(id, delay)
                resolve(id);
            }, delay, id);
        });
    }
}

const test_requests = [
    request(6000, 1),
    request(3000, 2),
    request(4000, 3),
    request(6000, 4),
    request(1000, 5),
    request(2000, 6),
]

function multiRequest(reqArr, limitNum) {
    return new Promise((resolve, reject) => {
        let count = 0; // 用来计算返回了几个结果了
        let result = [];
        let len = reqArr.length;
        let index = 0;
        function run() {
            const req = reqArr.shift();
            if (!req) {
                return;
            }
            // 注意保存当前的请求序号
            let cur = index++;
            return req().then(res => {
                result[cur] = res;
            }).catch(err => {
                result[cur] = err;
            }).finally(() => {
                count++;
                run();
                if (count === len) {
                    resolve(result);
                }
            })
        }
        for (let i = 0; i < limitNum; i++) {
            run();
        }
    });
}
multiRequest(test_requests, 3).then(res => console.log('success', res));

结果

image.png