题目
实现一个并发请求函数concurrencyRequest(urls, maxNum),要求如下:
- 要求最大并发数 maxNum
- 每当有一个请求返回,就留下一个空位,可以增加新的请求
- 所有请求完成后,结果按照 urls 里面的顺序依次打出(发送请求的函数可以直接使用fetch即可)
思路
- 函数返回一个promise
- maxNum要判断,取urls数组的length和maxNum的最小值
- count计算请求结果数量,如果count === len,则resolve结果
- 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));
结果如下:
再来一个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));
结果