手写异步并发

301 阅读1分钟

前端控制异步并发

  • 限制同时最大接口并发数量

代码

function fetch(url) {

  // 模拟接口请求

  return new Promise(resolve => {

   setTimeout(() => {

    resolve(url)

   }, 1000 * Math.random())

  })

 }

 

 function maxRequestLimit(arr, max, callback) {

  let reqList = []

  let i=0,count=0

  const rear = arr.length-max

  function getData() {

    if (i === arr.length) return Promise.resolve() //这里return 阻止继续下去

    let first = fetch(arr[i++])

    reqList.push(first)

    first.then(res => {

      count++

      reqList.splice(reqList.indexOf(first),1)

    })

    let p = Promise.resolve()

    if(reqList.length>=max && count!==rear) p = Promise.race(reqList)

    return p.then(()=>getData())

  }

  getData().then(()=> {

    Promise.all(reqList).then(() => callback())

  })

 }


 maxRequestLimit(['url1', 'url2', 'url3', 'url4', 'url5', 'url6', 'url7', 'url8'], 3, () => { console.log('fetch end') })

解析

首先用Promise.all和race-api- 并发和取出最快的那一个请求

核心代码解析

  • 每次请求经来都进行请求下一个fetch(arr[i++])
  • 所有请求都进去了-不再进行请求 if (i === arr.length) return Promise.resolve()
  • 拿到接口先让他异步执行-添加到reqList数组队列中
  • 执行完毕后自己在队列中进行删除使用 indexOf拿到自己的索引
if (i === arr.length) return Promise.resolve()
let first = fetch(arr[i++])
   reqList.pusnh(first)
   first.then(res => {
     count++
     reqList.splice(reqList.indexOf(first), 1)
   })
  • 执行队列reqList如果大于等于并发值 就需要race取出最快的一个-否则就是Promise.resolve()延迟执行
  • p.then(()=>getData()) 异步添加下一步的接口并发
let p = Promise.resolve()
if(reqList.length>=max && count!==rear) p = Promise.race(reqList)     
return p.then(()=>getData())
  • 执行getData异步then进行调用
  • Promise.all控制执行队列的并发
  • 队列执行完毕以后执行callback()
getData().then(() => {
   Promise.all(reqList).then(() => callback())
 })