作为一名前端工程师,该如何控制高并发请求呢?「如果有更好的方案,欢迎讨论」

假如现在有几十、上百个请求,我们该如何去控制这么高的并发呢?

给你一分钟时间,稍作思考 ~ 🤔

此场景有很多,比如 图片或文件批量下载、RSSHub高速抓取内容。。。

第一想法是不是请求池!!! 没错, 利用Promise模拟任务队列,从而实现请求池效果。

正文

众所周知,浏览器发起的请求最大并发数量一般都是 6~8 个,这是因为浏览器会限制同一域名下的并发请求数量,以避免对服务器造成过大的压力。

👇 先来模拟一下同时发起大量请求

// 模拟大量请求的函数
async function simulateConcurrentRequests(url, numberOfRequests) {
    const requests = Array.from({ length: numberOfRequests }, () => fetch(url));

    try {
        const responses = await Promise.all(requests);
        const results = await Promise.all(responses.map(response => response.json()));
        return results;
    } catch (error) {
        console.error('One or more requests failed:', error);
        return [];
    }
}

// 使用示例
const url = 'https://jsonplaceholder.typicode.com/posts/1'; // 示例URL
const numberOfRequests = 100; // 请求数量

simulateConcurrentRequests(url, numberOfRequests)
    .then(results => {
        console.log('All requests completed. Results:', results);
    })
    .catch(error => {
        console.error('Error during requests:', error);
    });
    

👇 效果如下:

在这里插入图片描述
一次性并发上百个请求,要是配置低一点,又或者带宽不够的服务器,直接宕机都有可能,所以我们前端这边是需要控制的并发数量去为服务器排忧解难「这样才能突出前端的高级」

首先 什么是队列?

先进先出就是队列push 一个的同时就会有一个被 shift。我们看下面的动图可能就会更加的理解:

在这里插入图片描述

我们了解了什么是队列,就可以模拟上图的队列行为来实现请求池。

1️⃣ 定义请求池函数,用于控制并发请求数量

// 基于队列控制并发请求数量
async function fetchWithConcurrency(url, totalRequests, maxConcurrency) {
    const results = [];
    let activeRequests = 0;
    let currentIndex = 0;

    async function fetchTask() {
        if (currentIndex >= totalRequests) return;

        const taskIndex = currentIndex++;
        activeRequests++;

        try {
            const response = await fetch(url);
            const data = await response.json();
            results[taskIndex] = data;
        } catch (error) {
            console.error('Request failed:', error);
            results[taskIndex] = null;
        } finally {
            activeRequests--;
            if (currentIndex < totalRequests) {
                await fetchTask();
            }
        }
    }

    const initialTasks = Array.from({ length: maxConcurrency }, fetchTask);
    await Promise.all(initialTasks);

    return results;
}

// 使用示例
const url = 'https://jsonplaceholder.typicode.com/posts/1'; // 示例URL
const totalRequests = 100; // 请求数量
const maxConcurrency = 10; // 并发请求数量限制

fetchWithConcurrency(url, totalRequests, maxConcurrency)
    .then(results => {
        console.log('All requests completed. Results:', results);
    })
    .catch(error => {
        console.error('Error during requests:', error);
    });
代码解释
  1. fetchWithConcurrency 函数:用于控制并发请求数量,接收三个参数:

    • url: 请求的URL。
    • totalRequests: 总请求数量。
    • maxConcurrency: 最大并发请求数量。
  2. 状态变量:

    let activeRequests = 0;
    let currentIndex = 0;
    

    用于跟踪当前活跃的请求数量和当前要处理的请求索引。

  3. fetchTask函数:负责处理单个请求任务。

    async function fetchTask() {
        if (currentIndex >= totalRequests) return;
    
        const taskIndex = currentIndex++;
        activeRequests++;
    
        try {
            const response = await fetch(url);
            const data = await response.json();
            results[taskIndex] = data;
        } catch (error) {
            console.error('Request failed:', error);
            results[taskIndex] = null;
        } finally {
            activeRequests--;
            if (currentIndex < totalRequests) {
                await fetchTask();
            }
        }
    }
    
    
    • 如果当前索引超过总请求数,任务结束。
    • 增加当前索引并增加活跃请求计数。
    • 发送请求并处理响应。
    • 无论请求成功与否,最终减少活跃请求计数,并检查是否需要处理下一个请求。
  4. 启动初始任务:

    const initialTasks = Array.from({ length: maxConcurrency }, fetchTask);
    await Promise.all(initialTasks);
    

    创建一个数组,长度为最大并发数,并启动相应数量的初始任务。使用 Promise.all 等待所有初始任务完成。

2️⃣ 测试

这种方法确保了在任何时间点,最多只有 maxConcurrency 个请求正在进行,从而实现真正的并发控制。

在这里插入图片描述
可以看出,请求数确实被控制了,只有有请求响应成功的同时才会有新的请求进来,极大的降低里服务器的压力,后端的同学都只能😲惊呼 6️⃣ 6️⃣ 6️⃣

  • 30
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值