需求:假如页面一次性请求有上百个,你应该如何处理这种请求并发?
答:so easy!循环请求?肯定是不对的,否则一次性并发上百次请求,差点的服务器得崩溃了,我甚至一度以为你是在搞Dos攻击。我们可以通过任务队列的缓存来合理控制并发数据。
我们知道浏览器发起的请求最大并发数量一般都是 6~8 个,这是因为浏览器会限制同一域名下的并发请求数量,以避免对服务器造成过大的压力。本文思路的核心就是保持浏览器的最大并发请求,多出的请求数加入队列缓存。
1. 实现并发请求场景
我们现实一下简单的100次直接并发请求的场景,本地实现一个简单的前端页面和express后台服务:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./axios.min.js"></script>
</head>
<body>
</body>
<script>
// 请求模拟
const requestFn = () => {
return axios.get("http://127.0.0.1:8000/msg", {})
}
// 模拟直接并发100次请求
for (let i = 0; i < 100; i++) {
requestFn();
}
</script>
</html>
const express = require('express');
const app = express();
app.all('*', (req,res,next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
next();
})
app.get("/msg", (req, res) => {
let count = 0;
for (let i = 0; i < 10000000; i++) {
count++
}
res.json({code :0, msg: `请求结果${count}`});
})
app.listen('8000',() => {
console.log('请求成功')
})
一次性并发上百个请求,要是配置低一点,又或者带宽不够的服务器,直接宕机都有可能,所以我们前端这边是需要控制的并发数量去为服务器排忧解难。
2. 优化并发请求场景
如下所示,定义一个 queue 用来缓存请求队列,定义一个参数 current 记录当前正常并发执行的接口请求数量。每一次循环请求时都会先将请求接口缓存在队列queue中,当前的并发的请求数量 current 小于默认最大的请求限制数量 limitCount时候,从队列头部中选择一个请求并开始执行,并且 current 数量+1,执行完成后current 数量-1,并且继续递归执行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./axios.min.js"></script>
</head>
<body>
</body>
<script>
// 请求模拟
const requestFn = () => {
return axios.get("http://127.0.0.1:8000/msg", {})
}
// 实现一个并发控制的函数
const queue = [] // 请求池队列,用来缓存接口请求
let current = 0
const requestQueue = (limitCount = 6, callbackFn) => {
queue.push(callbackFn); // 入队列
const dequeue = () => {
while (current < limitCount && queue.length) {
current++;
const requestPromiseFactory = queue.shift() // 出列
requestPromiseFactory()
.then((res) => {
console.log('res =====>', res)
})
.catch(error => { // 失败
console.log(error)
})
.finally(() => {
current--
dequeue()
});
}
}
// 执行
dequeue()
}
for (let i = 0; i < 100; i++) {
requestQueue(6, requestFn)
}
</script>
</html>
文章出自:https://juejin.cn/post/7360970130912411711
作者:阿镇吃橙子
标签:queue,const,请求,res,阁下,current,并发,百个,页面 From: https://www.cnblogs.com/o-O-oO/p/18546567