指定并发请求数量

163 阅读1分钟

以文件切片上传为例

创建文件切片

const createFileChunks = (file, size = 1024 * 1024 * 1) => {
    let fileChunks = [];
    if (file.size <= size) {
        return [file]
    }
    for (let cur = 0; cur < file.size; cur += size) {
        fileChunks.push(file.slice(cur, cur + size));
    }
    return fileChunks;
}

声明上传请求

const detailItem = ({ url, stepFile, partNumber, onSuccess, onError }) => {
    return new Promise((resolve, reject) => {
        axios({
            url,
            method: 'POST',
            data: stepFile,
        })
            .then((res) => {
                onSuccess?.(partNumber)
                resolve();
            })
            .catch((err) => {
                onError?.(partNumber)
                reject();
            });
    });
};

requestPool方法实现

poolLimit 同时请求的数量

array 请求参数

iteratorFn 实际请求方法,arrry的参数传入

async function requestPool(poolLimit, array, iteratorFn) {
    const ret = []; // 存储所有的异步任务
    const executing = []; // 存储正在执行的异步任务
    for (const item of array) {
        // 调用iteratorFn函数创建异步任务
        const p = Promise.resolve().then(() => iteratorFn(item, array));
        ret.push(p); // 保存新的异步任务
        
        // 当poolLimit值小于或等于总任务个数时,进行并发控制
        if (poolLimit <= array.length) {
            // 当任务完成后,从正在执行的任务数组中移除已完成的任务
            const e = p.then(() => executing.splice(executing.indexOf(e), 1));
            executing.push(e); // 保存正在执行的异步任务
            if (executing.length >= poolLimit) {
                await Promise.race(executing); // 等待较快的任务执行完成
            }
        }
    }
    return Promise.all(ret)
}

处理参数,发起请求

       const uploadFileChunks = (fileChunks, filename)=> {
            const chunksList = fileChunks.map((chunk, index) => {
                let formData = new FormData();
                //formData.append('...', ...);
                
                return {
                    url: '请求地址',
                    stepFile: formData,
                    fname: filename,
                    //partNumber:当前切片的唯一标识
                    partNumber: index,
                    onError: (index) => {
                        console.log('上传失败', index);
                    },
                    onSuccess: (index) => {
                        console.log('上传成功', index);
                    }
                };
            });
            //发起请求
            requestPool(5, chunksList, detailItem).then(() => {
                //全部上传完成,发起合并请求
            }).catch(() => {
                //处理上传失败
            })
        },