并发请求

133 阅读3分钟

并发请求

1.什么是并发请求

​ 并发请求指的是同一时间发出多个请求,当其中一个请求结束的时候,在发送另一个请求,同时保证有多个请求一直在发送中,提高文件的传输效率

2.完成代码

<template>
  <el-button @click="concurRequest()">并发请求</el-button>
</template>
<script setup>
import { demoRequest } from "@/api/demo.js";

//并发请求的封装
const concurRequest = (allRequestNumber = 4, maxnumber = 3, errorRequest = 3) => {
  let requestNumber = 0; // 接口调用了多少次
  let requestResult = []; // 请求结果
  let requestFinish = 0; // 代表请求完成的数量
  //  Math.min(allRequestNumber, maxnumber) 请求的数量,和并发的数量取最小值,避免请求数量小于并发数量引起报错
  //  for循环模拟并发请求
  for (let index = 0; index < Math.min(allRequestNumber, maxnumber); index++) {
    getRequest();
  }
  function getRequest() {
    let oldIndeX = requestNumber;
    requestNumber++;
    let errorCount = 0; // 记录报错重发的次数
    const request = () =>
      demoRequest()
        .then((res) => {
          if (res.code === 200) {
            res.index = oldIndeX;
            //记录成功结果
            requestResult[oldIndeX] = res;
            //接口成功继续进行调用
            if (requestNumber < allRequestNumber) {
              getRequest();
            }
          }
        })
        .catch((error) => {
          if (errorCount < errorRequest) {
            //进行报错的重发
            errorCount++;
            request();
          } else {
            //记录失败结果
            requestResult[oldIndeX] = {
              msg: "请求失败",
              index: oldIndeX
            };
          }
        })
        .finally(() => {
          requestFinish++;
          if (requestFinish >= allRequestNumber) {
            // 当所有的接口结束之后输出最后的请求结果
            console.log("requestResult", requestResult);
          }
        });
    request();
  }
};

// const demo = () => {
//   let request = () =>
//     demoRequest()
//       .then((res) => {
//         if (res.code === 200) {
//           //接口成功继续进行调用

//           request();
//         }
//       })
//       .catch((error) => {
//         return Promise.resolve(request());
//       });
//   request();
// };
</script>


3.注意事项

1. 在使用el-button 组件的时候,调用函数如果不加上‘()’ 而是直接使用函数名进行调用,会有默认的 pointEvent 参数传递,函数中接收的第一个参数就会变成默认的pointEvent 参数。
<template>
<el-button @click="concurRequest">并发请求</el-button>
</template>
<script setup>
import { demoRequest } from "@/api/demo.js";
//并发请求的封装
const concurRequest = (allRequestNumber = 10, maxnumber = 3) => {
  for (let index = 0; index < Math.min(allRequestNumber, maxnumber); index++) {
    demoRequest()
  }
  demoRequest()
        .then((res) => {
        })
        .catch((error) => {
        })
        .finally(() => {
        });
  
};


</script>

2.由于接口直接写法方法里面进行调用,会导致除 循环外的次数,还会多调用一次,与预想的次数不一致,所以在接口调用,用一个函数在进行包裹下,也为了形成闭包保存接口调用时候的参数,可以用来接口调用失败的时候进行重发

3.由于需要进行报错的时候进行重发,所以接口请求外面还需要包裹一层函数来进行重发,并记录报错次数

4.记录请求结果的时候,不能使用push直接添加,而是用 index 来进行数组的赋值,因为先发出去的请求不一定就是先完成的

5.记录请求全部完成的时候是在 finally 来进行记录请求全部完成

4. 不同地址不同数据的并发请求

/**
 * 并发请求,不限制请求地址,不限制请求数据
 * @param {请求地址以及请求传递的数据} urlDate
 * @param {需要发送的请求的次数} allRequestNumber
 * @param {最大并发数} maxnumber
 * @param {报错重发的次数} errorRequest
 */
const concurRequestOthers = (urlDate, allRequestNumber = urlDate.length, maxnumber = 3, errorRequest = 3) => {
  let requestNumber = 0; // 接口调用了多少次
  let requestResult = []; // 请求结果
  let requestFinish = 0; // 代表请求完成的数量
  //  Math.min(allRequestNumber, maxnumber) 请求的数量,和并发的数量取最小值,避免请求数量小于并发数量引起报错
  //  for循环模拟并发请求
  for (let index = 0; index < Math.min(allRequestNumber, maxnumber); index++) {
    getRequest();
  }
  function getRequest() {
    let oldIndeX = requestNumber;
    requestNumber++;
    let errorCount = 0; // 记录报错重发的次数
    const request = () =>
      urlDate[oldIndeX]
        .url(urlDate[oldIndeX].data)
        .then((res) => {
          if (res.code === 200) {
            res.index = oldIndeX;
            //记录成功结果
            requestResult[oldIndeX] = res;
            //接口成功继续进行调用
            if (requestNumber < allRequestNumber) {
              getRequest();
            }
          }
        })
        .catch((error) => {
          //重发3回共4回
          if (errorCount < errorRequest) {
            //进行报错的重发
            errorCount++;
            request();
          } else {
            //记录失败结果
            requestResult[oldIndeX] = {
              msg: "请求失败",
              index: oldIndeX
            };
          }
        })
        .finally(() => {
          requestFinish++;
          if (requestFinish >= allRequestNumber) {
            // 当所有的接口结束之后输出最后的请求结果
            console.log("requestResult", requestResult);
          }
        });
    request();
  }
};

export default concurRequestOthers;