MST

星途 面试题库

面试题:Vue 项目中文件上传与下载的并发控制及异常处理

在一个复杂的 Vue 应用场景下,存在多个文件同时上传和下载的需求。请设计一个方案,实现对这些文件操作的并发控制,确保同一时间只有特定数量的任务在执行,并妥善处理可能出现的各种网络异常,如超时、断网恢复等,给出详细的实现思路和关键代码架构。
24.1万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 任务队列:创建一个任务队列来存储所有需要上传或下载的文件任务。
  2. 并发控制:使用一个计数器来跟踪当前正在执行的任务数量,确保同一时间执行的任务数量不超过特定值。
  3. 网络异常处理
    • 超时:为每个任务设置超时时间,使用 Promise.race 结合 setTimeout 实现。
    • 断网恢复:通过 window.addEventListener('online', callback) 监听网络恢复事件,重新启动因断网暂停的任务。

关键代码架构

  1. 任务队列和并发控制
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();
                });
        }
    }
}
  1. 文件上传/下载任务
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();
    });
}
  1. 使用任务队列
// 创建任务队列,设置最大并发数为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));
});
  1. 处理超时
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);
        })
    ]);
}
  1. 处理断网恢复
window.addEventListener('online', () => {
    // 重新启动任务队列
    taskQueue.runNextTask();
});