前端如何处理「并发」问题?

举报
猫先生c 发表于 2023/09/28 09:17:59 2023/09/28
【摘要】 在项目中我们会遇到一次请求多个接口,当所有请求结束后进行操作,也会遇到多个请求(大量)同时进行请求资源,本文就并发问题通过axios对这两种现象进行优化处理,主要通过 axios中all、spread、请求拦截以及响应拦截进行处理。 axios中all、spreadaxios的all和spread都是axios的静态方法,可以直接通过axios对象调用。all:用于并发控制,接收一个包含多个...

在项目中我们会遇到一次请求多个接口,当所有请求结束后进行操作,也会遇到多个请求(大量)同时进行请求资源,本文就并发问题通过axios对这两种现象进行优化处理,主要通过 axios中all、spread、请求拦截以及响应拦截进行处理。

axios中all、spread

axiosallspread都是axios的静态方法,可以直接通过axios对象调用。

  • all:用于并发控制,接收一个包含多个Promsie对象的数组,多个Promsie也就是多个请求。最终返回一个Promise,这个Promise只有当所有的请求结束后才会被解析。
  • spread:用于处理多个并发请求的结果。接收一个回调函数作为参数,并将每个请求的结果作为独立的参数传递给回调函数。
const foo = () => {
  return  axios.get("https://dog.ceo/api/breeds/image/random ")
}  

const bar = () => {
  return  axios.get("https://dog.ceo/api/breeds/list/all")
     
};
axios.all([foo(), bar()]).then(
    axios.spread( (acct, perms) =>{
        console.log(acct,'acct');
        console.log(perms,'perms');
    })
);

定义的foobar必须要把axios的请求return,这样得到的才是一个Promise对象。结果如下:

在这里插入图片描述

axios请求拦截、响应拦截

声明三个变量:请求队列、最大并发请求数、当前并发请求数

const requestQueue = []; // 请求队列
const maxConcurrent = 3; // 最大并发请求数
let concurrentRequests = 0; // 当前并发请求数

在请求拦截中,如果当前并发请求数没超过最大并发请求数,当前并发请求数就加1,否则就将请求添加到请求队列中,其中config是当前请求的配置,resolve是解析函数。

//请求拦截设置
import axios from "axios";
axios.interceptors.request.use(
    (config) => {
      console.log(config,'concurrentRequests')
        if (concurrentRequests < maxConcurrent) {
            console.log('000000')
            // 如果并发请求数量小于最大并发数,直接发送请求
            concurrentRequests++;
            return config;
        } else {
            // 如果并发请求数量达到最大并发数,将请求添加到队列中
            return new Promise((resolve) => {
                console.log('333333')
                requestQueue.push({
                    config,
                    resolve,
                });
            });
        }
    },
    (error) => {
        return Promise.reject(error);
    }
);

在这里插入图片描述

打印结果如下:

在这里插入图片描述

在响应拦截中,并发请求数量减1,如果请求队列的长度大于0,说明有等待的请求,通过shift取出队列中的最早的请求,同时在请求队列中删除该请求。然后当前并发请求数加1,通过resolve(config)触发解析函数发送请求。当调用解析函数时,相当于将 Promise 的状态从待定(pending)转变为已解析(resolved),并将传递的参数作为解析值。失败的话并发请求数量减1,抛出异常。

//响应拦截
axios.interceptors.response.use(
    (response) => {
        concurrentRequests--; // 并发请求数量减2
        if (requestQueue.length > 0) {
            // 如果请求队列中有等待的请求,发送下一个请求
            const { config, resolve } = requestQueue.shift();
            concurrentRequests++;
            resolve(config);
        }
        return response.data;
    },
    (error) => {
        concurrentRequests--; // 并发请求数量减一
        return Promise.reject(error);
    }
);

这里模仿了10个请求进行测试,具体如下:

// 发送请求
for (let i = 0; i < 10; i++) {
  axios
    .get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      // 处理响应
      console.log(response.data);
    })
    .catch((error) => {
      // 处理错误
      console.error(error);
    });
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。