題目
假設(shè)有這么一個(gè)場(chǎng)景:現(xiàn)在有20個(gè)異步請(qǐng)求需要發(fā)送,但是由于HTTP客戶端一般對(duì)同一個(gè)服務(wù)器的并發(fā)連接個(gè)數(shù)都是有限制的,比如chrome瀏覽器同一時(shí)刻最大并發(fā)數(shù)是6。
實(shí)現(xiàn)一個(gè)并發(fā)請(qǐng)求函數(shù)concurrencyRequest(urls, maxNum),要求如下:
- 要求最大并發(fā)數(shù) maxNum
- 每當(dāng)有一個(gè)請(qǐng)求返回,就留下一個(gè)空位,可以增加新的請(qǐng)求
- 所有請(qǐng)求完成后,結(jié)果按照 urls 里面的順序依次打出(發(fā)送請(qǐng)求的函數(shù)可以直接使用fetch即可)
測(cè)試代碼
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);
})
復(fù)制代碼
具體實(shí)現(xiàn)
// 并發(fā)請(qǐng)求函數(shù)
const concurrencyRequest = (urls, maxNum) => {
// 因?yàn)闇y(cè)試代碼調(diào)用concurrencyRequest后需要返回一個(gè)Promise
return new Promise((resolve) => {
// urls的長度為0時(shí),results就沒有值,此時(shí)應(yīng)該返回空數(shù)組
if (urls.length === 0) {
resolve([]);
return;
}
const results = [];
let index = 0; // 下一個(gè)請(qǐng)求的下標(biāo)
let count = 0; // 當(dāng)前請(qǐng)求完成的數(shù)量
// 發(fā)送請(qǐng)求
async function request() {
if (index === urls.length) return;
const i = index; // 保存序號(hào),使result和urls相對(duì)應(yīng)
const url = urls[index];
index++;
console.log(url);
try {// 請(qǐng)求成功
const res = await fetch(url);
// resp 加入到results
results[i] = res;
} catch (err) {// 請(qǐng)求失敗
// err 加入到results
results[i] = err;
} finally {// 請(qǐng)求失敗或成功都補(bǔ)一個(gè)新的請(qǐng)求進(jìn)來
// 請(qǐng)求完成計(jì)數(shù)器
count++;
// 判斷是否所有的請(qǐng)求都已完成
if (count === urls.length) {
console.log('完成了');
resolve(results);
}
//
request();
}
}
// maxNum大于urls的長度時(shí),應(yīng)該取的是urls的長度,否則則是取maxNum
const times = Math.min(maxNum, urls.length);
// 開啟第一次批量調(diào)用
for(let i = 0; i < times; i++) {
request();
}
})
}
復(fù)制代碼
思路
- 首先按照每次只能并發(fā)3個(gè)請(qǐng)求的要求,這里就對(duì)應(yīng)A、B、C,當(dāng)其中有一個(gè)請(qǐng)求完之后就會(huì)再從urls里面再取出一個(gè)進(jìn)行請(qǐng)求,這樣依次類推,直到urls里面的20個(gè)請(qǐng)求都執(zhí)行完才終止請(qǐng)求。
- urls的長度為0時(shí),results就沒有值,此時(shí)應(yīng)該返回空數(shù)組
- maxNum大于urls的長度時(shí),應(yīng)該取的是urls的長度,否則則是取maxNum
- 需要單獨(dú)定義一個(gè)count計(jì)數(shù)器來判斷是否已全部請(qǐng)求完成;
- 因?yàn)闆]有考慮請(qǐng)求是否請(qǐng)求成功,所以請(qǐng)求成功或報(bào)錯(cuò)都應(yīng)把結(jié)果保存在results集合中
- results中的順序需和urls中的保持一致