MST

星途 面试题库

面试题:JavaScript 异步编程中 Promise 的异常处理与链式调用优化

假设有一个需求,需要依次发起三个异步请求(可以用 `fetch` 模拟,也可以自行定义异步函数),每个请求依赖前一个请求的结果。在这个过程中,任何一个请求失败都要捕获并处理异常,同时要确保整个流程尽可能高效。请用 Promise 链式调用的方式实现该需求,并解释你对异常处理的思路以及如何优化链式调用的性能。
30.2万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
function asyncRequest1() {
    return new Promise((resolve, reject) => {
        // 模拟异步请求
        setTimeout(() => {
            Math.random() > 0.5? resolve('result1') : reject(new Error('Request 1 failed'));
        }, 1000);
    });
}

function asyncRequest2(result1) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5? resolve(result1 + ' -> result2') : reject(new Error('Request 2 failed'));
        }, 1000);
    });
}

function asyncRequest3(result2) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            Math.random() > 0.5? resolve(result2 + ' -> result3') : reject(new Error('Request 3 failed'));
        }, 1000);
    });
}

asyncRequest1()
   .then(result1 => asyncRequest2(result1))
   .then(result2 => asyncRequest3(result2))
   .then(finalResult => {
        console.log(finalResult);
    })
   .catch(error => {
        console.error('An error occurred:', error.message);
    });

异常处理思路

  1. 链式调用中的异常捕获:在Promise链式调用中,只要其中一个Promise被拒绝(rejected),后续的.then() 回调函数将不会被执行,而是直接跳转到最近的.catch() 回调函数。这确保了一旦某个请求失败,异常能被及时捕获并处理,避免未处理的异常导致程序崩溃。
  2. 统一的异常处理:通过在链式调用的末尾添加.catch() 回调函数,可以捕获整个链式调用过程中任何一个Promise抛出的异常。这样可以对所有可能的异常进行统一处理,例如记录日志、显示错误信息给用户等。

性能优化

  1. 减少不必要的中间变量:在链式调用中,尽量避免创建过多的中间变量来存储Promise的结果。直接将前一个Promise的结果作为参数传递给下一个Promise的处理函数,这样可以减少内存占用,提高性能。
  2. 合理设置异步任务:在实际应用中,确保异步任务(如网络请求、文件读取等)本身是优化过的。例如,合理设置请求超时时间,避免长时间等待无响应的请求,从而提高整个流程的效率。
  3. 复用Promise:如果某些异步操作在链式调用中会重复出现,可以考虑复用已经创建好的Promise对象,而不是每次都创建新的Promise,这样可以减少创建Promise的开销。