- 簡易實作
- 完善實作
請實作如下的函式(發請求的函式可以直接使用fetch)
- 可以批量請求資料,所有的URL地址在urls引數中
- 同時可以通過max引數 控制請求的并發度
- 當所有的請求結束后,需要執行callback回呼
function sendRequest (urls: string[], max: number, callback: () => void) {}
fetch 函式回傳的是一個promise,promise物件在實體化的時候就已經開始執行了,
簡易實作
function fetch(url) {
// 模擬介面請求
return new Promise(resolve => {
setTimeout(() => {
resolve(url)
}, 10000*Math.random())
})
}
/**
* 介面請求最大并發量控制
* @param { Array } urls 介面請求地址陣列集合
* @param { Number } max 最大并發量
* @param { Function } callback 回呼函式
*/
function maxRequestLimit(urls, max, callback) {
// 如果沒有傳入urls或max則不繼續執行
if (!urls || !max) return
// 當請求地址陣列集合長度為0,則執行回呼函式(如果有的話),并結束后續執行
if(urls.length === 0) {
if(callback) callback()
return
}
// 使用splice方法回傳當前要使用的請求集合,同時洗掉原有的請求集合
const onceMaxUrlArr = urls.splice(0, max)
// 進行map轉換,將url引數轉換為promise
const onceMaxFetchArr = onceMaxUrlArr.map(url => fetch(url))
// 使用當前這一佇列
Promise.all(onceMaxFetchArr)
.then(res => {
console.log(res)
// 遞回請求
maxRequestLimit(urls, max, callback)
})
}
maxRequestLimit(['url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7', 'url8'], 3, () => {console.log('fetch end')})
上面的簡易實作是一個佇列一個佇列進行請求,實際運行效果會存在一定的阻塞,下面通過進一步改善來提高請求的效率
完善實作
function fetch(url) {
// 模擬介面請求
return new Promise(resolve => {
setTimeout(() => {
resolve(url)
}, 10000 * Math.random())
})
}
/**
* 介面請求最大并發量控制
* @param { Array } urls 介面請求地址陣列集合
* @param { Number } max 最大并發量
* @param { Function } callback 回呼函式
*/
function maxRequestLimit(arr, max, callback) {
// 如果沒有傳入urls或max則不繼續執行
if (!arr || !max) return
// 當請求地址陣列集合長度為0,則執行回呼函式(如果有的話),并結束后續執行
if(arr.length === 0) {
if(callback) callback()
return
}
let fetchArr = [], // 存盤并發max的promise陣列
i = 0;
function toFetch() {
// 所有的請求都受理,則回傳一個resolve
if (i === arr.length) return Promise.resolve()
// 取出第i個url, 放入fetch里面 , 每取一次i++
let one = fetch(arr[i++])
//將當前的promise存入并發陣列中
fetchArr.push(one)
// 當promise執行完畢后,從陣列洗掉
one.then(res => {
console.log(res)
fetchArr.splice(fetchArr.indexOf(one), 1)
})
let p = Promise.resolve()
// 當并行數量達到最大后, 用race比較 第一個完成的, 然后再呼叫一下函式自身,
if (fetchArr.length >= max) p = Promise.race(fetchArr)
return p.then(() => toFetch())
}
// arr回圈完后, 現在fetchArr里面剩下的promise物件, 使用all等待所有的都完成之后執行callback
toFetch()
.then(() => Promise.all(fetchArr))
.then(() => callback())
}
maxRequestLimit(['url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7', 'url8'], 3, () => { console.log('fetch end') })
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/226238.html
標籤:其他
