写点什么

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

作者:不叫猫先生
  • 2023-06-19
    北京
  • 本文字数:1598 字

    阅读完需:约 5 分钟

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

在项目中我们会遇到一次请求多个接口,当所有请求结束后进行操作,也会遇到多个请求(大量)同时进行请求资源,本文就并发问题通过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);    });}
复制代码


发布于: 刚刚阅读数: 3
用户头像

还未添加个人签名 2022-10-18 加入

前端领域优质创作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀!

评论

发布
暂无评论
前端如何处理「并发」问题?_并发_不叫猫先生_InfoQ写作社区