以文件切片上传为例
创建文件切片
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(() => {
//处理上传失败
})
},