js并发请求,且限制并发请求数量实现方案

说明

  • 前端会遇到这种需求,希望多个请求并发加快前端反应速度,但又要限制同时请求的数量,防止服务器压力过大
  • 以下代码由Trae里的千问模型生成,思路真牛

方案

js 复制代码
async function batchQuset(){
      this.$store.commit('openLoading')
      const questNum = this.paramsList.length
      // 每批最多 3 个并发请求
      const BATCH_SIZE = 3
      // 保持顺序的结果数组
      const numResList = new Array(questNum).fill(null) 
      // 并发控制函数
      const runWithConcurrency = async (tasks, concurrency) => {
        const results = []
        // 维护一个正在执行的 Promise 列表(控制并发就靠它)
        const executing = []
        for (const task of tasks) {
          // p 是 then() 方法返回的新 Promise,不是 task() 的原始 Promise
          const p = task().then((result) => {
            // 当task执行完成后,从executing数组中移除
            executing.splice(executing.indexOf(p), 1)
            return result
          })
          results.push(p)
          executing.push(p)
          // 当正在执行的任务数量超过并发限制时,等待任意一个完成
          if (executing.length >= concurrency) {
            // 等有完成的Promise时,外面的for循环才能继续走
            await Promise.race(executing)
          }
        }
        // 走到这里时,仅剩下小于并发数量的Promise还没彻底完成
        return Promise.all(results)
      }
      // 创建所有校验任务[Promise,Promise]
      const tasks = this.paramsList.map(
        (params, index) => async () => {
          const { pass, res } = await questApi(params)
          this.$store.commit(
            'openLoading',
            `进度: ${index + 1}/${questNum}`
          )
          return { index, pass, res }
        }
      )
      // 执行并发校验
      const results = await runWithConcurrency(tasks, BATCH_SIZE)
      // 按原始顺序填充结果
      results.forEach(({ index, pass, res }) => {
        if (!pass) {
          numResList[index] = res
        }
      })
      // 过滤掉 null 值,得到最终的列表
      const resList = numResList.filter((item) => item !== null)
      this.$store.commit('closeLoading')
      // *****请求结果resList进行展示/处理******
}

说明

  • this.$store.commit('openLoading')是自己把element的loading二次封装,方便唤起和改文字
js 复制代码
import Vuex from "vuex";
import { Loading } from 'element-ui';
export default new Vuex.Store({
    state: {
    // 全屏loading实例
    loading: null,
    },
    mutations:{
     openLoading(state, str) {
      if (state.loading) {
        state.loading.setText(str)
      } else {
        state.loading = Loading.service({
          lock: true,
          text: str,
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)',
          customClass: 'phone-loading'
        })
      }
    },
    closeLoading(state) {
      state.loading?.close()
      state.loading = null
    },
    }
})
  • then 中 return result 的作用 :
    • 当 then 的回调函数执行完毕后, p 这个 Promise 会被 resolve
    • p 被 resolve 的值就是 return 后面的值
    • 如果 return result ,则 p 解析为 result
    • 如果不 return 或 return undefined ,则 p 解析为 undefined
js 复制代码
// 示例 1:return result
const p1 = task().then((result) => {
  console.log('收到 result:', result)  // 假设 result = '任务完成'
  return result  // return '任务完成'
})

p1.then((value) => {
  console.log('p1 的值:', value)  // 输出:'任务完成'
})

// 示例 2:不 return
const p2 = task().then((result) => {
  console.log('收到 result:', result)  // 假设 result = '任务完成'
  // 没有 return 语句
})

p2.then((value) => {
  console.log('p2 的值:', value)  // 输出:undefined
})

// 示例 3:return 其他值
const p3 = task().then((result) => {
  console.log('收到 result:', result)  // 假设 result = '任务完成'
  return '修改后的值'
})

p3.then((value) => {
  console.log('p3 的值:', value)  // 输出:'修改后的值'
})
相关推荐
Chengbei1140 分钟前
云安全漏洞挖掘SKILL、一站式云漏洞挖掘工具,支持S3爆破、IMDS探测、K8s检测与AK/SK权限利用
前端·人工智能·网络安全·云原生·容器·kubernetes·系统安全
不简说1 小时前
JS 代码技巧 vol.9 — 20 个设计模式在真实项目里的应用
前端·javascript·github
CoderLiu1 小时前
Agent 工程的下一层:为什么「把流程写成图」还不够,还需要 Graph Engineering
前端·人工智能·后端
勇往直前plus1 小时前
Vue3(篇三) Element Plus
前端·javascript·typescript·vue
爱勇宝1 小时前
《道德经》第 8 章:真正高级的能力,像水一样成事
前端·后端·程序员
Revolution612 小时前
数组本身没有 map,为什么还能直接调用:原型链怎样查找属性
前端·javascript·面试
bonechips2 小时前
RAG实战(一):EPUB 加载、文本切割与向量入库
前端·数据库
swipe2 小时前
10|(前端转全栈)库存扣减为什么最容易出事故?SKU、并发与原子更新
前端·后端·全栈
cdcdhj2 小时前
vue3中的watchEffect()监听,什么时候监听,什么时候清理,什么时候停止
前端·javascript·vue.js
huabuyu2 小时前
几百 MB 的文件为什么等几分钟才能打开?文件分片下载与渐进预览原理
前端·javascript