最近领导给了一个需求——大文件上传,由于文件过大(几百MB),故而采取了分片上传机制,将大文件分割成了多个小分片进行上传;此时出现了这样一个问题:
这时,就需要控制分片上传请求的并发数不能占满 6 个,影响其他请求下发;这个问题可以转化成实现一个并发请求函数concurrencyRequest(urls, maxNum),要求如下:
- 最大并发数
maxNum= 3;- 每当有一个请求返回,就留下一个空位,可以增加新的请求;
- 所有请求完成后,结果按照
urls顺序依次打印出来,返回一个results集合;
需要考虑的特殊情况:
urls 的长度为 0,results 为空数组;maxNum 大于 urls 的长度,应该取的是 urls 的长度;count 计数器来判断是否已全部请求完成;results 集合中;results 中的顺序需和 urls 中的保持一致;// 并发请求函数
const concurrencyRequest = (urls, maxNum) => {
return new Promise((resolve) => {
// 特殊情况,urls长度为0
if (urls.length === 0) {
resolve([]);
return;
}
const results = [];
let index = 0; // 下一个请求的下标
let count = 0; // 当前请求完成的数量
// 发送请求,一个请求结束之后才能进行下一个请求
async function request() {
if (index === urls.length) return;
const i = index; // 保存序号,使results和urls相对应
const url = urls[index];
index++;
console.log(`第${i}个 url`, url);
try {
const resp = await fetch(url);
// resp 加入到results
results[i] = resp;
} catch (err) {
// err 加入到results
results[i] = err;
} finally {
count++;
// 判断是否所有的请求都已完成
if (count === urls.length) {
console.log('完成了所有的请求');
resolve(results);
}
request();
}
}
// maxNum和urls.length取最小进行调用
const times = Math.min(maxNum, urls.length);
for(let i = 0; i < times; i++) {
request();
}
})
}
测试代码
const urls = [];
for (let i = 1; i <= 20; i++) {
urls.push(`https://jsonplaceholder.typicode.com/todos/${i}`);
}
concurrencyRequest(urls, 3).then(res => {
console.log(res);
});