一批请求的发送方式

26 阅读1分钟

做业务时,会遇到有多个请求要连续发送的情况,常见下面两种处理方式

1. 多个请求同时发送,请求池里有完成的下一个顶上

手写

// 同时发送5个请求,有完成的,下一个跟上
async function batchRequest(items, successFuc) {
  const maxConcurrentRequests = 5
  const requestsQueue = []
  const paramsBase = {
    userId: this.userId,
  }
  this.resObj.total = items.length
  const calcMaskText = () => {
    const successCount = this.resObj.successList.length
    const failureCount = this.resObj.failList.length
    const process = Math.floor(
      ((successCount + failureCount) / items.length) * 100
    )
    return `成功修改${successCount}条,失败${failureCount}条,共${items.length}条,执行进度:${process}%`
  }

  for (const item of items) {
    const params = { ...paramsBase, customerIdList: [item] }
    const request = remarkUpdate(params)
      .then((res) => {
        if (res.code === 0) {
          if (res.data) {
            this.resObj.successList.push(item)
            this.$store.commit('openLoading', calcMaskText())
          } else {
            this.resObj.failList.push(item)
            this.$store.commit('openLoading', calcMaskText())
          }
        } else {
          this.resObj.failList.push(item)
          this.$store.commit('openLoading', calcMaskText())
        }
      })
      .catch(() => {
        this.$store.commit('closeLoading')
        return
      })

    // 添加到当前正在处理的 promises 列表
    requestsQueue.push(request)

    // 如果达到了最大并发数,等待其中一个完成
    if (requestsQueue.length >= maxConcurrentRequests) {
      await Promise.race(requestsQueue)
      // 移除已完成的请求
      const index = requestsQueue.findIndex(
        (req) => req.isFulfilled || req.isRejected
      )
      if (index !== -1) requestsQueue.splice(index, 1)
    }
  }

  // 等待所有剩余的 promises 完成
  await Promise.all(requestsQueue)
  this.$store.commit('closeLoading')
  successFuc && successFuc()
}

可以用第三方库

  • npm install p-limit
import pLimit from 'p-limit';

const limit = pLimit(5);// Returns a `limit` function.控制并发量

const input = [
	limit(() => fetchSomething('foo')),
	limit(() => fetchSomething('bar')),
	limit(() => doSomething())
];

// Only one promise is run at once
const result = await Promise.all(input);
console.log(result);

2. 一堆请求,一个接一个地发

async function batchRequest(items, successFuc) {
  const paramsBase = {
    userId: this.userId,
  }
  this.resObj.total = items.length
  const calcMaskText = () => {
    const successCount = this.resObj.successList.length
    const failureCount = this.resObj.failList.length
    const process = Math.floor(
      ((successCount + failureCount) / items.length) * 100
    )
    return `成功修改${successCount}条,失败${failureCount}条,共${items.length}条,执行进度:${process}%`
  }

  for (const item of items) {
    const params = { ...paramsBase, customerIdList: [item] }
    try {
      const res = await remarkUpdate(params)
      if (res.code === 0) {
        if (res.data) {
          this.resObj.successList.push(item)
          this.$store.commit('openLoading', calcMaskText())
        } else {
          this.resObj.failList.push(item)
          this.$store.commit('openLoading', calcMaskText())
        }
      } else {
        this.resObj.failList.push(item)
        this.$store.commit('openLoading', calcMaskText())
      }
    } catch (error) {
      this.resObj.failList.push(item)
      this.$store.commit('openLoading', calcMaskText())
    }
  }

  this.$store.commit('closeLoading')
  successFuc && successFuc()
}