1. 程式人生 > 程式設計 >js非同步介面併發數量控制的方法示例

js非同步介面併發數量控制的方法示例

請實現如下的函式(發請求的函式可以直接使用fetch)

  1. 可以批量請求資料,所有的URL地址在urls引數中
  2. 同時可以通過max引數 控制請求的併發度
  3. 當所有的請求結束後,需要執行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,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,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',() => { console.log('fetch end') })

總結

到此這篇關於js非同步介面併發數量控制的文章就介紹到這了,更多相關js非同步介面併發數量控制內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!