• 前端如何控制并发请求数量?


    最近领导给了一个需求——大文件上传,由于文件过大(几百MB),故而采取了分片上传机制,将大文件分割成了多个小分片进行上传;此时出现了这样一个问题:

    1. 浏览器支持并发请求,谷歌浏览器貌似是从59版本开始,支持并发请求数为 6
    2. 大文件共分了100片,待请求资源就有100个,依次排队,它们在一定时间内会占用全部的并发请求数,导致其他请求无法下发。

    这时,就需要控制分片上传请求的并发数不能占满 6 个,影响其他请求下发;这个问题可以转化成实现一个并发请求函数concurrencyRequest(urls, maxNum),要求如下:

    • 最大并发数 maxNum = 3;
    • 每当有一个请求返回,就留下一个空位,可以增加新的请求;
    • 所有请求完成后,结果按照urls顺序依次打印出来,返回一个results集合;

    需要考虑的特殊情况:

    • urls 的长度为 0results 为空数组;
    • maxNum 大于 urls 的长度,应该取的是 urls 的长度;
    • 需要定义一个 count 计数器来判断是否已全部请求完成;
    • 由于没有考虑请求是否请求成功,所以请求成功或报错都应该把结果保存在 results 集合中;
    • results 中的顺序需和 urls 中的保持一致;
    // 并发请求函数
    const concurrencyRequest = (urls, maxNum) => {
        return new Promise((resolve) => {
        	// 特殊情况,urls长度为0
            if (urls.length === 0) {
                resolve([]);
                return;
            }
            
            const results = []; 
            let index = 0; // 下一个请求的下标
            let count = 0; // 当前请求完成的数量
    
            // 发送请求,一个请求结束之后才能进行下一个请求
            async function request() {
                if (index === urls.length) return;
                const i = index; // 保存序号,使results和urls相对应
                const url = urls[index];
                index++;
                console.log(`${i}个 url`, url);
                try {
                    const resp = await fetch(url);
                    // resp 加入到results
                    results[i] = resp;
                } catch (err) {
                    // err 加入到results
                    results[i] = err;
                } finally {
                    count++;
                    // 判断是否所有的请求都已完成
                    if (count === urls.length) {
                        console.log('完成了所有的请求');
                        resolve(results);
                    }
                    request();
                }
            }
    
            // maxNum和urls.length取最小进行调用
            const times = Math.min(maxNum, urls.length);
            for(let i = 0; i < times; i++) {
                request();
            }
        })
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    测试代码

    const urls = [];
    for (let i = 1; i <= 20; i++) {
        urls.push(`https://jsonplaceholder.typicode.com/todos/${i}`);
    }
    concurrencyRequest(urls, 3).then(res => {
        console.log(res);
    });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    在 Ubuntu 22.04安装配置 Ansible
    确保企业物联网部署安全的5个基本步骤
    测试行业面临的问题及RunnerGo在工具层面如何解决的
    【Linux】线程安全-死锁
    有哪些做流程图的软件?分享一些制作方法和注意事项
    【python笔记】第四节 序列类型初始
    Kubectl
    Git 学习(2)
    c++ fmt
    [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(二)XSS注入相关面试题
  • 原文地址:https://blog.csdn.net/weixin_45678402/article/details/132825512