面试题答案
一键面试使用 try...catch
处理异步操作错误
async/await
中使用try...catch
:- 当使用
async/await
时,try...catch
可以很好地捕获异步操作中的错误。例如:
async function asyncFunction() { try { const result1 = await someAsyncOperation1(); const result2 = await someAsyncOperation2(result1); // 其他异步操作 return finalResult; } catch (error) { // 处理所有在上述异步操作中抛出的错误 console.error('An error occurred:', error); // 可以根据错误类型进行不同处理,或者重新抛出错误 if (error instanceof CustomError) { // 特定处理 } else { // 通用处理 } } }
- 这里
await
会暂停函数执行,直到 Promise 被解决(resolved)或被拒绝(rejected)。如果 Promise 被拒绝,await
会抛出错误,这个错误会被catch
块捕获。
- 当使用
Promise
链式调用中使用catch
:- 在使用
Promise
链式调用时,在链的末尾添加.catch
来捕获整个链中的错误。例如:
someAsyncOperation1() .then(result1 => someAsyncOperation2(result1)) .then(result2 => { // 处理结果 return finalResult; }) .catch(error => { // 捕获所有在上述 Promise 操作中抛出的错误 console.error('An error occurred:', error); // 类似地,可根据错误类型处理 });
- 在使用
Promise.all
和 Promise.race
的错误处理
Promise.all
:Promise.all
接受一个 Promise 数组,当所有 Promise 都被解决时,返回一个新的已解决的 Promise,其值为所有 Promise 结果组成的数组。如果任何一个 Promise 被拒绝,Promise.all
会立即被拒绝,并抛出第一个被拒绝的 Promise 的错误。- 使用
try...catch
或.catch
处理错误:
async function allPromiseFunction() { try { const results = await Promise.all([ someAsyncOperation1(), someAsyncOperation2() ]); // 处理 results 数组 return finalResult; } catch (error) { // 捕获第一个被拒绝的 Promise 的错误 console.error('An error occurred in Promise.all:', error); } }
- 也可以在每个 Promise 内部处理错误,然后在
Promise.all
外部根据结果进行处理:
const promises = [ someAsyncOperation1().catch(error => { // 在这里处理第一个 Promise 的错误 console.error('Error in someAsyncOperation1:', error); return null; }), someAsyncOperation2().catch(error => { // 在这里处理第二个 Promise 的错误 console.error('Error in someAsyncOperation2:', error); return null; }) ]; Promise.all(promises).then(results => { // 处理 results 数组,其中可能包含 null return finalResult; });
Promise.race
:Promise.race
接受一个 Promise 数组,返回第一个被解决或被拒绝的 Promise。- 使用
try...catch
或.catch
处理错误:
async function racePromiseFunction() { try { const result = await Promise.race([ someAsyncOperation1(), someAsyncOperation2() ]); // 处理第一个完成的 Promise 的结果 return finalResult; } catch (error) { // 捕获第一个被拒绝的 Promise 的错误 console.error('An error occurred in Promise.race:', error); } }
自定义错误的设计和使用策略
- 自定义错误类:
- 创建一个继承自
Error
的自定义错误类。例如:
class CustomError extends Error { constructor(message) { super(message); this.name = 'CustomError'; // 可以添加其他自定义属性 this.customProperty = 'Some custom value'; } }
- 创建一个继承自
- 抛出自定义错误:
- 在异步操作中,根据业务逻辑抛出自定义错误。例如:
async function someAsyncOperation() { if (someCondition) { throw new CustomError('This is a custom error'); } return result; }
- 捕获和处理自定义错误:
- 在
try...catch
块中,根据错误类型进行不同处理:
async function mainFunction() { try { await someAsyncOperation(); } catch (error) { if (error instanceof CustomError) { console.error('Custom error occurred:', error.message); // 可以根据自定义属性进行特定处理 console.log('Custom property:', error.customProperty); } else { console.error('Other error occurred:', error.message); } } }
- 在
- 提高可维护性和错误排查效率:
- 通过自定义错误,可以清晰地标识错误来源和类型,使代码的维护者更容易理解错误发生的原因。
- 自定义错误可以携带更多与业务相关的信息,如错误发生时的上下文数据,帮助快速定位和解决问题。在复杂的异步操作中,这有助于区分不同类型的错误,提高错误排查的效率。