VUE解决页面请求接口大规模并发的问题(请求队列)

发布于:2025-06-07 ⋅ 阅读:(23) ⋅ 点赞:(0)

方案1: 请求队列

// RequestQueue.js 
export default class RequestQueue {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent; // 最大并发请求数
    this.currentConcurrent = 0; // 当前并发请求数
    this.queue = []; // 请求队列
    this.requestId = 0; // 请求ID计数器
  }

  add(request, meta = {}) {
    return new Promise((resolve, reject) => {
      const id = ++this.requestId;
      this.queue.push({
        id,
        request: () => request().then(res => ({
          id,
          res
        })), // 响应携带ID
        resolve,
        reject,
        meta, // 可携带业务标识
      });
      this.processQueue();
    })
  }

  processQueue() {
    while (this.queue.length > 0 && this.currentConcurrent < this.maxConcurrent) {
      const task = this.queue.shift();
      this.currentConcurrent++;

      task.request()
        .then(({
          id,
          res
        }) => {
          task.resolve({
            id,
            meta: task.meta,
            data: res
          }); // 返回完整响应
        })
        .catch(task.reject)
        .finally(() => {
          this.currentConcurrent--;
          this.processQueue();
        });
    }
  }
}

组件调用

import request from '@/utils/request.js'; /** axios的二次封装 */
import RequestQueue from '@/utils/RequestQueue.js';


// 使用请求队列
const requestQueue = new RequestQueue(3); // 设定最大并发请求数

const urls = [
  {
    url: '/slider/getSliders',
    method: '', // 请求方法
    data: '',  //  请求参数
    id: 1,
    reqType: 'getSliders' // 请求唯一标识符
  },
  {
    url: '/course/mostNew',
    method: 'post',
    data: newCoursePageInfo,
    id: 2,
    reqType: 'mostNew'
  },
  {
    url: '/course/search',
    method: 'post',
    data: interestCoursePageInfo,
    id: 3,
    reqType: 'search'
  }
];

// 请求函数:
const fetchData = ({ url, method, data }) => {
  return request(url, data, method).then((res) => {
    return res;
    // res.json();  // 如果是Fetch API必须要显式调用.json()方法解析响应体,注释上边用这个
  });
};

const requests = urls.map((url) => () => fetchData(url));


onLoad(() => {
  Promise.all(requests.map((req, idx) => requestQueue.add(req, { originalIndex: idx, reqType: urls[idx].reqType }))).then((results) => {
    // results包含[{id, meta, data},...]  data:响应回的数据
    results.forEach(({ meta, data }) => {
      switch (meta.reqType) {
        case 'getSliders':   // 请求唯一标识符
          swiperList.value = data.list; 
          break;
        case 'mostNew':
          interestCouseInfo.value.push(...data.pageInfo.list);
          break;
        case 'search':
          newCourseInfo.value = data.pageInfo.list.slice(3, 9);
          break;
      }

      console.log(`请求${meta.originalIndex}(${meta.reqType})结果:`, data);
    });
  });
});

说明:

  • reqType: 请求唯一标识符,用于将并行发出的请求与响应回的数据对应上
  • request: 对axios做的二次封装,函数fetchData 发出的请求就好比在api文件中的请求函数在这里插入图片描述只需在 对象urls变动url(id可不需要,唯一标识符必须) 和在 results赋值即可

网站公告

今日签到

点亮在社区的每一天
去签到