MST

星途 面试题库

面试题:TypeScript中async函数在复杂场景下的性能优化与资源管理

在一个大型TypeScript项目中,存在大量依赖外部API的异步操作,这些操作有的需要并发执行,有的需要顺序执行,并且要考虑资源的合理利用(例如:避免同时发起过多请求导致资源耗尽)。请描述你会采用什么样的策略和技术手段来优化这些异步代码,同时在代码层面给出关键部分的示例实现。
50.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

策略

  1. 并发控制:使用队列或信号量机制来限制并发请求的数量,确保不会同时发起过多请求耗尽资源。
  2. 任务编排:对于需要顺序执行的异步操作,使用 async/awaitPromise.then() 链式调用实现顺序执行。对于并发执行的异步操作,使用 Promise.all()Promise.race() 进行处理。

技术手段

  1. async/await:它是基于 Promise 的语法糖,使异步代码看起来像同步代码,提高代码可读性。
  2. Promise.all():用于并行执行多个 Promise,当所有 Promise 都 resolved 时返回一个 resolved 的 Promise,当其中任何一个 Promise 被 rejected 时返回一个 rejected 的 Promise
  3. Promise.race():同样并行执行多个 Promise,但只要其中一个 Promise 被 resolved 或 rejected,就返回该 Promise 的结果。
  4. 队列实现并发控制:可以通过自定义队列,将异步任务按顺序放入队列,每次从队列中取出一定数量的任务并发执行,完成后再从队列中取出新的任务执行。

关键部分示例实现

顺序执行异步操作

async function sequentialOperations() {
    const result1 = await asyncOperation1();
    const result2 = await asyncOperation2(result1);
    const result3 = await asyncOperation3(result2);
    return result3;
}

async function asyncOperation1(): Promise<string> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('Operation 1 result');
        }, 1000);
    });
}

async function asyncOperation2(input: string): Promise<string> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(`${input}, Operation 2 result`);
        }, 1000);
    });
}

async function asyncOperation3(input: string): Promise<string> {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(`${input}, Operation 3 result`);
        }, 1000);
    });
}

并发执行异步操作

async function concurrentOperations() {
    const [result1, result2, result3] = await Promise.all([asyncOperation1(), asyncOperation2(), asyncOperation3()]);
    return `${result1}, ${result2}, ${result3}`;
}

并发控制示例(使用队列)

class TaskQueue {
    private tasks: (() => Promise<void>)[] = [];
    private runningCount = 0;
    private maxConcurrent: number;

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

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

    private async runNext() {
        while (this.runningCount < this.maxConcurrent && this.tasks.length > 0) {
            const task = this.tasks.shift();
            if (task) {
                this.runningCount++;
                try {
                    await task();
                } finally {
                    this.runningCount--;
                    this.runNext();
                }
            }
        }
    }
}

// 使用示例
const queue = new TaskQueue(3); // 最大并发数为3
queue.addTask(() => asyncOperation1());
queue.addTask(() => asyncOperation2());
queue.addTask(() => asyncOperation3());