前端如何处理「并发」问题?
1468 浏览2023年07月04日作者:Mr_Cat

分享开发经验瓜分5000元大奖,聊聊#我写代码那些年#的故事

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

axios中all、spread

`axios`的`all`和`spread`都是`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');

})

);

定义的`foo`和`bar`必须要把`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);

});

}
最后一次编辑于 2023 年 07 月 04 日
2 条评论

相关文章

专题推荐

热门文章

热门问答