有这样一个问题,在发送一个大文件时会用到分片处理,或者其他批量认证用户的时候,如果一个地址一个地址发送用户体验会特别差,或者有个文件特别大,请求等待时间长,这个情况体验会非常不好,我查阅了一些资料和视频做了下面的并发请求

image.png

/**
 * 并发请求  用于大文件分片
 * @param { string[] } urls  待请求的 url 数据
 * @param { number } maxNum 最大并发数据
*/

// 功能: concurrently 请求多个 url,并返回请求结果
// 参数:urls:url数组;maxNum:最大并发请求数
function concurRequest(urls, maxNum) {
    if (!urls || !urls.length) {
        // 如果urls为空,则返回空数组
        return new Promise((resolve, reject) => {
            resolve([]);
        })
    }
    // 使用 Promise 实例化一个异步操作,用于处理并发请求
    return new Promise((resolve, reject) => {
        let index = 0; // 指向下一次请求坐标
        let results = []; // 存储请求结果
        async function _request() {
            const i = index;
            const url = urls[i];
            index += 1;
            try {
                // 使用 fetch 函数发起请求
                const resp = await fetch(url);
                // 将请求结果存储在 results 数组中
                results[i] = resp;
            } catch (error) {
                // 如果请求失败,将错误存储在 results 数组中
                results[i] = error;
            }

        }

        _request()
        _request()
        _request()
    })
}

目前看着请求数据是没有问题,目前只是做了三次请求,但是还有一个最大的问题就是怎么去做最大请求数,还需要考虑的一个问题就是什么时候请求下一个, 我们可以这样认为当前有一个请求完了,就请求下一项

function concurRequest(urls, maxNum) {
    if (!urls || !urls.length) {
        // 如果urls为空,则返回空数组
        return new Promise((resolve, reject) => {
            resolve([]);
        })
    }
    // 使用 Promise 实例化一个异步操作,用于处理并发请求
    return new Promise((resolve, reject) => {
        let index = 0; // 指向下一次请求坐标
        let results = []; // 存储请求结果
        async function _request() {
            const i = index;
            const url = urls[i];
            index += 1;
            try {
                // 使用 fetch 函数发起请求
                const resp = await fetch(url);
                // 将请求结果存储在 results 数组中
                results[i] = resp;
            } catch (error) {
                // 如果请求失败,将错误存储在 results 数组中
                results[i] = error;
            }
            finally {
                if (index < urls.length) {
                    _request()
                }
            }
        }
        _request()
        _request()
        _request()
    })
}

最终还要考虑一个问题就是正 promise 什么时候完,也就是说当某一个请求完成,要返回所有的数据

function concurRequest(urls, maxNum) {
    if (!urls || !urls.length) {
        // 如果urls为空,则返回空数组
        return new Promise((resolve, reject) => {
            resolve([]);
        })
    }
    return new Promise((resolve, reject) => {
        let index = 0; // 指向下一次请求坐标
        let results = []; // 存储请求结果
        let count = 0; // 当前正在进行的请求数
        async function _request() {
            const i = index;
            const url = urls[i];
            index ++;
            try {
                const resp = await fetch(url);
                results[i] = resp;
            } catch (error) {
                results[i] = error;
            } finally {
                count++;
                if( count == urls.length){
                    // 当所有请求都完成时,将结果 resolve 出去
                    resolve(results);
                }
                if (index < urls.length) {
                    _request()
                }
            }
        }
        for (let i = 0; i < maxNum && i < urls.length; i++) {
            _request();
        }
    })
}

还请各位大佬进行评论,感谢!!!


loong
39 声望0 粉丝