并发请求

111 阅读4分钟

并发请求

1.什么是并发请求

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

2.注意事项

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>

image-20231230201603260

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

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

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

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

3.完成代码

<template>
  <el-button @click="concurRequest()">并发请求</el-button>
  <el-button @click="getOther()">并发不同的数据,不同的接口</el-button>
</template>
<script setup>
import { demoRequest, demoRequestTwo, demoRequestThree } from "@/api/demo.js";
import concurRequestOthers from "../untils/requestAll.js";
//并发请求的封装
const concurRequest = (allRequestNumber = 10, 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) {
            //记录成功结果
            requestResult[oldIndeX] = res;
            requestFinish++;
              if (requestFinish == allRequestNumber) {
                // 当所有的接口结束之后输出最后的请求结果
                resolve(requestResult);
              }
            //接口成功继续进行调用
            if (requestNumber < allRequestNumber) {
              getRequest();
            }
          }
        })
        .catch((error) => {
          //接口成功继续进行调用
          if (errorCount < errorRequest) {
            //进行报错的重发
            errorCount++;
            request();
          } else {
            //记录失败结果
            requestResult[oldIndeX] = {
              msg: "请求失败",
              index: oldIndeX
            };
            requestFinish++;
              if (requestFinish == allRequestNumber) {
                // 当所有的接口结束之后输出最后的请求结果
                resolve(requestResult);
              }
            if (requestNumber < allRequestNumber) {
              getRequest();
            }
          }
        })
    request();
  }
};
​
// const demo = () => {
//   let request = () =>
//     demoRequest()
//       .then((res) => {
//         if (res.code === 200) {
//           //接口成功继续进行调用
​
//           request();
//         }
//       })
//       .catch((error) => {
//         return Promise.resolve(request());
//       });
//   request();
// };
​
// 并发请求不限制 url 不限制请求数据
const urlDate = [
  {
    url: demoRequest,
    data: {
      msg: "接口请求1"
    }
  },
  {
    url: demoRequestTwo,
    data: {
      msg: "接口请求2"
    }
  },
  {
    url: demoRequestThree,
    data: {
      msg: "接口请求3"
    }
  },
  {
    url: demoRequestTwo,
    data: {
      msg: "接口请求4"
    }
  },
  {
    url: demoRequestThree,
    data: {
      msg: "接口请求5"
    }
  }
];
​
const getOther = async () => {
 concurRequestOthers(urlDate);
  // console.log("result", result);
};
</script>
​

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

/**
 * 并发请求,不限制请求地址,不限制请求数据
 * @param {请求地址以及请求传递的数据} urlDate
 * @param {需要发送的请求的次数} allRequestNumber
 * @param {最大并发数} maxnumber
 * @param {报错重发的次数} errorRequest
 */
const concurRequestOthers = (urlDate, allRequestNumber = urlDate.length, maxnumber = 3, errorRequest = 3) => {
  return new Promise((resolve, reject) => {
    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;
              requestFinish++;
              if (requestFinish == allRequestNumber) {
                // 当所有的接口结束之后输出最后的请求结果
                resolve(requestResult);
              }
              //接口成功继续进行调用
              if (requestNumber < allRequestNumber) {
                getRequest();
              }
            }
          })
          .catch((error) => {
            //重发3回共4回
            if (errorCount < errorRequest) {
              //进行报错的重发
              errorCount++;
              request();
            } else {
              //记录失败结果
              requestFinish++;
              if (requestFinish == allRequestNumber) {
                // 当所有的接口结束之后输出最后的请求结果
                resolve(requestResult);
              }
              if (requestNumber < allRequestNumber) {
                getRequest();
              }
              requestResult[oldIndeX] = {
                msg: "请求失败",
                index: oldIndeX
              };
            }
          })
      request();
    }
  });
};