MST

星途 面试题库

面试题:TypeScript 异步编程的性能优化与资源管理

在一个复杂的 TypeScript 项目中,存在大量的异步任务,这些任务包括网络请求、文件读写等。请阐述如何对这些异步任务进行性能优化(如任务并发控制、资源复用等),并且结合 TypeScript 的特性,设计一个通用的异步任务管理模块,该模块需要具备任务调度、资源监控与回收等功能。请给出详细的设计思路与关键代码示例。
48.8万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

异步任务性能优化策略

  1. 任务并发控制
    • 在 TypeScript 中,可以使用 Promise.all 来并发执行多个异步任务。但如果任务数量过多,可能会导致资源耗尽。例如,在进行大量网络请求时,过多的并发请求可能会使服务器压力过大,同时客户端网络带宽也可能被占满。
    • 可以通过队列和计数器来实现并发控制。比如设置一个最大并发数 maxConcurrent,当任务执行时计数器加一,任务完成时计数器减一,只有当计数器小于 maxConcurrent 时,才从队列中取出新任务执行。
  2. 资源复用
    • 对于网络请求,可以复用网络连接池。在 Node.js 中,http 模块的 Agent 对象可以实现连接池功能。例如,在发起 HTTP 请求时,可以设置 agent 选项来复用已有的连接。
    • 文件读写方面,可以复用文件描述符。在 Node.js 中,通过 fs.open 打开文件获取文件描述符后,后续的读写操作都可以使用这个描述符,而不是每次读写都重新打开文件。

异步任务管理模块设计思路

  1. 任务调度
    • 采用队列的方式来管理任务。每个任务封装成一个函数,当任务加入队列时,按照一定规则(如先进先出)等待执行。
    • 利用 async/await 来处理异步任务,使代码更简洁易读。
  2. 资源监控与回收
    • 对于网络连接等资源,可以通过计数器记录资源的使用情况。当资源使用完毕(如网络请求完成),计数器减一,当计数器为 0 时,可以考虑回收资源(如关闭网络连接)。
    • 对于文件描述符,在任务完成后,及时关闭文件描述符以释放资源。

关键代码示例

class TaskManager {
    private taskQueue: (() => Promise<void>)[] = [];
    private runningTasks: number = 0;
    private maxConcurrent: number;

    constructor(maxConcurrent: number) {
        this.maxConcurrent = maxConcurrent;
    }

    addTask(task: () => Promise<void>) {
        this.taskQueue.push(task);
        this.executeNextTask();
    }

    private async executeNextTask() {
        while (this.runningTasks < this.maxConcurrent && this.taskQueue.length > 0) {
            const task = this.taskQueue.shift();
            if (task) {
                this.runningTasks++;
                try {
                    await task();
                } catch (error) {
                    console.error('Task execution error:', error);
                } finally {
                    this.runningTasks--;
                    this.executeNextTask();
                }
            }
        }
    }
}

// 示例使用
const manager = new TaskManager(5);

// 模拟异步任务
const asyncTask1 = async () => {
    // 模拟网络请求或文件读写等异步操作
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log('Task 1 completed');
};

const asyncTask2 = async () => {
    await new Promise(resolve => setTimeout(resolve, 1500));
    console.log('Task 2 completed');
};

manager.addTask(asyncTask1);
manager.addTask(asyncTask2);

以上代码实现了一个简单的异步任务管理模块,通过设置最大并发数 maxConcurrent 来控制任务并发执行,利用队列来调度任务。同时,在任务执行完毕后,通过 finally 块来更新任务计数并继续执行下一个任务。