实现思路
- 任务队列:创建一个任务队列来存储所有需要上传或下载的文件任务。
- 并发控制:使用一个计数器来跟踪当前正在执行的任务数量,确保同一时间执行的任务数量不超过特定值。
- 网络异常处理:
- 超时:为每个任务设置超时时间,使用
Promise.race
结合 setTimeout
实现。
- 断网恢复:通过
window.addEventListener('online', callback)
监听网络恢复事件,重新启动因断网暂停的任务。
关键代码架构
- 任务队列和并发控制
class TaskQueue {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent;
this.taskQueue = [];
this.runningCount = 0;
}
addTask(task) {
this.taskQueue.push(task);
this.runNextTask();
}
runNextTask() {
while (this.runningCount < this.maxConcurrent && this.taskQueue.length > 0) {
const task = this.taskQueue.shift();
this.runningCount++;
task()
.then(() => {
this.runningCount--;
this.runNextTask();
})
.catch((error) => {
console.error('Task failed:', error);
this.runningCount--;
this.runNextTask();
});
}
}
}
- 文件上传/下载任务
function uploadFile(file) {
return new Promise((resolve, reject) => {
// 模拟上传逻辑
const xhr = new XMLHttpRequest();
xhr.open('POST', 'upload-url', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve();
} else {
reject(new Error('Upload failed'));
}
}
};
xhr.send(file);
});
}
function downloadFile(url) {
return new Promise((resolve, reject) => {
// 模拟下载逻辑
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error('Download failed'));
}
}
};
xhr.send();
});
}
- 使用任务队列
// 创建任务队列,设置最大并发数为3
const taskQueue = new TaskQueue(3);
// 添加上传任务
const filesToUpload = [file1, file2, file3, file4];
filesToUpload.forEach((file) => {
taskQueue.addTask(() => uploadFile(file));
});
// 添加下载任务
const urlsToDownload = ['url1', 'url2', 'url3'];
urlsToDownload.forEach((url) => {
taskQueue.addTask(() => downloadFile(url));
});
- 处理超时
function uploadFileWithTimeout(file, timeout) {
return Promise.race([
uploadFile(file),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('Upload timed out'));
}, timeout);
})
]);
}
function downloadFileWithTimeout(url, timeout) {
return Promise.race([
downloadFile(url),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('Download timed out'));
}, timeout);
})
]);
}
- 处理断网恢复
window.addEventListener('online', () => {
// 重新启动任务队列
taskQueue.runNextTask();
});