MST

星途 面试题库

面试题:TypeScript 错误处理与异步操作的深度结合

在 TypeScript 中,当处理复杂的异步操作(如多个 Promise 并发或链式调用)时,错误处理变得尤为关键。请实现一个场景,包含多个异步任务,使用 `async/await` 语法,要求能够优雅地处理每个任务可能出现的错误,同时避免未处理的 Promise 拒绝,并且利用类型系统确保错误处理的健壮性和准确性。请详细解释代码逻辑及错误处理策略。
27.2万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
// 模拟异步任务函数,成功时返回结果,失败时抛出错误
function asyncTask1(): Promise<string> {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5? resolve('Task 1 Success') : reject(new Error('Task 1 Error'));
        }, 1000);
    });
}

function asyncTask2(): Promise<string> {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5? resolve('Task 2 Success') : reject(new Error('Task 2 Error'));
        }, 1500);
    });
}

function asyncTask3(): Promise<string> {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5? resolve('Task 3 Success') : reject(new Error('Task 3 Error'));
        }, 2000);
    });
}

// 并发执行多个异步任务并处理错误
async function concurrentTasks() {
    try {
        const [result1, result2, result3] = await Promise.all([asyncTask1(), asyncTask2(), asyncTask3()]);
        console.log(result1, result2, result3);
    } catch (error) {
        if (error instanceof Error) {
            console.error('Concurrent Task Error:', error.message);
        } else {
            console.error('Unexpected Error:', error);
        }
    }
}

// 链式调用异步任务并处理错误
async function chainedTasks() {
    try {
        const result1 = await asyncTask1();
        console.log(result1);
        const result2 = await asyncTask2();
        console.log(result2);
        const result3 = await asyncTask3();
        console.log(result3);
    } catch (error) {
        if (error instanceof Error) {
            console.error('Chained Task Error:', error.message);
        } else {
            console.error('Unexpected Error:', error);
        }
    }
}

// 调用并发任务
concurrentTasks();
// 调用链式任务
chainedTasks();

代码逻辑解释

  1. 异步任务函数asyncTask1asyncTask2asyncTask3 模拟了实际的异步任务,它们通过 setTimeout 模拟了异步操作,并以一定概率成功或失败。成功时通过 resolve 返回结果,失败时通过 reject 抛出错误。
  2. 并发任务处理:在 concurrentTasks 函数中,使用 Promise.all 并发执行三个异步任务。await Promise.all([asyncTask1(), asyncTask2(), asyncTask3()]) 等待所有任务完成,并将结果以数组形式返回。如果其中任何一个任务失败,Promise.all 会立即拒绝,并抛出该任务的错误。
  3. 链式任务处理:在 chainedTasks 函数中,通过 await 依次调用 asyncTask1asyncTask2asyncTask3,形成链式调用。只有前一个任务成功完成,才会执行下一个任务。如果某个任务失败,后续任务将不会执行,await 会捕获并抛出错误。

错误处理策略

  1. try...catch:在 concurrentTaskschainedTasks 函数中,使用 try...catch 块捕获可能出现的错误。这样可以确保在异步操作出现错误时,不会出现未处理的 Promise 拒绝。
  2. 类型检查:在 catch 块中,使用 instanceof Error 进行类型检查,确保捕获的错误是 Error 类型。这样可以更准确地处理错误,避免在处理非 Error 类型数据时出现意外情况。对于非 Error 类型的错误,也进行了相应的日志记录,以帮助调试。通过这种方式,利用 TypeScript 的类型系统确保了错误处理的健壮性和准确性。