在 async await 环境下如何自定义错误抛出

作者:袖梨 2026-07-16
在 async/await 中自定义错误需继承 Error 类并用 throw 抛出实例,确保堆栈、instanceof 判断正常;调用处用 try/catch 捕获,按 error.name 或 instanceof 区分类型做差异化处理。

在 async/await 环境下自定义错误抛出,核心是用 throw 抛出一个继承自 Error 的实例(或至少具备 messagename 属性的对象),并在调用处用 try/catch 捕获处理。

定义可识别的自定义错误类

推荐继承原生 Error 类,确保堆栈信息、instanceof 判断和调试体验正常:

  • 构造函数中调用 super(message),并设置 this.name
  • 可添加额外属性(如 codestatus)用于业务区分
  • 避免只抛字符串或普通对象,否则难以统一拦截和类型判断
示例:
class ValidationError extends Error {  constructor(message, field) {    super(message);    this.name = 'ValidationError';    this.code = 'VALIDATION_ERROR';    this.field = field;  }}// 使用async function createUser(data) {  if (!data.email) {    throw new ValidationError('邮箱不能为空', 'email');  }  // ...}

在 await 后主动检查并抛出自定义错误

async 函数本身不会自动将 rejected Promise 转为自定义错误;需显式判断响应或结果,再决定是否抛出:

  • 调用第三方 API 后,检查 response.status 或返回体中的 error 字段
  • 不依赖 catch 原始错误,而是根据业务逻辑“翻译”成领域错误
  • 避免直接 throw err(可能丢失上下文),建议包装后再抛
示例:
async function fetchUser(id) {  const res = await fetch(`/api/users/${id}`);  const data = await res.json();  if (!res.ok) {    throw new ApiError(`请求失败: ${data.message || res.statusText}`, {      status: res.status,      code: data.code    });  }  if (!data.user) {    throw new NotFoundError('用户不存在');  }  return data.user;}

统一错误处理与中间层封装

在大型项目中,可在请求函数或业务方法外层做标准化错误转换:

  • 封装一个 safeAwait 工具函数,自动将 Promise rejection 映射为自定义错误
  • 在 API 客户端中统一拦截 HTTP 错误码,映射为 NetworkErrorAuthError
  • 避免每个 await 都写重复的 if (res?.error) 判断
小技巧: 用 try/catch 包裹单个 await 更清晰,不建议把多个 await 塞进一个 try 块里——否则无法准确定位哪一步出错。

在 catch 中精准识别和响应自定义错误

利用 instanceoferror.name 区分错误类型,实现差异化处理:

  • ValidationError 提示表单字段问题
  • AuthError 触发登出或跳转登录页
  • 对未知错误兜底显示通用提示,并上报监控系统
示例:
try {  await submitForm(data);} catch (err) {  if (err instanceof ValidationError) {    showFieldError(err.field, err.message);  } else if (err instanceof AuthError) {    redirectToLogin();  } else {    notifyUser('操作失败,请稍后重试');    reportError(err);  }}

相关文章

精彩推荐