MST

星途 面试题库

面试题:JavaScript 异步操作中的错误处理策略

在 JavaScript 的 Web 编程中,经常会使用到异步操作,比如 Promise、async/await。请阐述在这些异步场景下错误是如何传递和处理的。以一个包含多个异步操作的购物流程为例,详细说明如何确保每个异步步骤出现错误时都能得到恰当处理,同时避免错误导致整个流程崩溃。
30.4万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
  1. Promise 错误传递与处理
    • 错误传递:在 Promise 链中,当一个 Promise 被拒绝(rejected)时,它会将错误传递给链中的下一个 catch 块。例如,在购物流程中,可能有获取商品信息、添加到购物车、下单等异步操作,假设获取商品信息使用 Promise:
    function getProductInfo() {
        return new Promise((resolve, reject) => {
            // 模拟异步操作,这里可能因为网络等原因失败
            setTimeout(() => {
                const success = false;
                if (success) {
                    resolve({ product: 'example product' });
                } else {
                    reject(new Error('Failed to get product info'));
                }
            }, 1000);
        });
    }
    function addToCart(product) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                const success = true;
                if (success) {
                    resolve({ message: 'Added to cart' });
                } else {
                    reject(new Error('Failed to add to cart'));
                }
            }, 1000);
        });
    }
    function placeOrder() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                const success = true;
                if (success) {
                    resolve({ message: 'Order placed' });
                } else {
                    reject(new Error('Failed to place order'));
                }
            }, 1000);
        });
    }
    getProductInfo()
       .then(product => addToCart(product))
       .then(() => placeOrder())
       .catch(error => {
            console.error('Error in shopping process:', error.message);
        });
    
    • 处理方式:通过 catch 块捕获错误,catch 块可以放在 Promise 链的任何位置,通常放在链的末尾统一处理整个流程中的错误。也可以在每个 Promise 后单独添加 catch 块处理该步骤的错误,比如:
    getProductInfo()
       .catch(error => {
            console.error('Error getting product info:', error.message);
            // 可以选择在这里返回一个新的 Promise 继续后续流程,或者直接结束
            return Promise.reject(error);
        })
       .then(product => addToCart(product))
       .catch(error => {
            console.error('Error adding to cart:', error.message);
            return Promise.reject(error);
        })
       .then(() => placeOrder())
       .catch(error => {
            console.error('Error placing order:', error.message);
        });
    
  2. async/await 错误传递与处理
    • 错误传递async 函数返回一个 Promise,当 await 一个被拒绝的 Promise 时,会抛出错误,这个错误可以被 try...catch 块捕获。在购物流程中,如果使用 async/await
    async function shoppingProcess() {
        try {
            const product = await getProductInfo();
            await addToCart(product);
            await placeOrder();
            console.log('Shopping process completed successfully');
        } catch (error) {
            console.error('Error in shopping process:', error.message);
        }
    }
    shoppingProcess();
    
    • 处理方式:使用 try...catch 块包裹 await 语句来捕获错误。如果希望在每个步骤单独处理错误,可以在每个 await 处分别使用 try...catch
    async function shoppingProcess() {
        let product;
        try {
            product = await getProductInfo();
        } catch (error) {
            console.error('Error getting product info:', error.message);
            return;
        }
        try {
            await addToCart(product);
        } catch (error) {
            console.error('Error adding to cart:', error.message);
            return;
        }
        try {
            await placeOrder();
        } catch (error) {
            console.error('Error placing order:', error.message);
            return;
        }
        console.log('Shopping process completed successfully');
    }
    shoppingProcess();
    
  3. 确保流程不崩溃
    • 使用 catch 块或 try...catch 处理错误:如上述示例,无论是 Promise 还是 async/await,通过捕获错误并进行相应处理(如记录错误、提示用户等),避免错误向上抛出导致整个流程崩溃。
    • 提供默认值或回退逻辑:在捕获错误后,可以根据业务需求提供默认值或执行回退逻辑。例如,在获取商品信息失败时,可以提供一个默认的商品信息给后续添加到购物车的步骤,不过这种情况需要根据具体业务场景来决定是否可行。
    • 重试机制:对于一些可能因为临时网络问题等导致的错误,可以实现重试机制。例如,在获取商品信息失败时,进行有限次数的重试,代码如下:
    async function getProductInfoWithRetry(maxRetries = 3) {
        let retries = 0;
        while (retries < maxRetries) {
            try {
                return await getProductInfo();
            } catch (error) {
                retries++;
                console.log(`Retry ${retries} failed:`, error.message);
                if (retries === maxRetries) {
                    throw error;
                }
            }
        }
    }
    async function shoppingProcess() {
        try {
            const product = await getProductInfoWithRetry();
            await addToCart(product);
            await placeOrder();
            console.log('Shopping process completed successfully');
        } catch (error) {
            console.error('Error in shopping process:', error.message);
        }
    }
    shoppingProcess();