Project Icon

modern-errors

强大而灵活的JavaScript错误处理库

modern-errors是一个功能丰富的JavaScript错误处理库。它简化了错误类的创建、属性设置、错误包装和聚合等操作,并能有效区分已知和未知错误。该库以稳定性著称,拥有全面的测试覆盖和严格的TypeScript类型支持。通过插件系统,modern-errors还可扩展多种功能,如命令行界面错误处理、进程错误管理和错误序列化等。

modern-errors 标志

Node 浏览器 TypeScript Codecov 压缩后大小 Mastodon Medium

以简单、稳定、一致的方式处理错误。

招聘我

如果您正在寻找一位 Node.js API 或 CLI 工程师(具有11年经验),请联系我。我最近在 Netlify BuildNetlify Plugins 担任技术主管2.5年。我可以接受全职远程职位。

特性

简单的模式用于:

稳定性:

插件

示例

创建错误

import ModernError from 'modern-errors'

export const BaseError = ModernError.subclass('BaseError')

export const UnknownError = BaseError.subclass('UnknownError')
export const InputError = BaseError.subclass('InputError')
export const AuthError = BaseError.subclass('AuthError')
export const DatabaseError = BaseError.subclass('DatabaseError')

设置错误属性

throw new InputError('无效的文件路径', { props: { filePath: '/...' } })

包装错误。

try {
  // ...
} catch (cause) {
  throw new InputError('无法读取文件。', { cause })
}

规范化错误。

try {
  throw '缺少文件路径。'
} catch (error) {
  // 从字符串规范化为 `BaseError` 实例
  throw BaseError.normalize(error)
}

使用插件

import ModernError from 'modern-errors'
import modernErrorsSerialize from 'modern-errors-serialize'

export const BaseError = ModernError.subclass('BaseError', {
  plugins: [modernErrorsSerialize],
})

// ...

// 将错误序列化为 JSON,然后再解析回相同的错误实例
const error = new InputError('缺少文件路径。')
const errorString = JSON.stringify(error)
const identicalError = BaseError.parse(JSON.parse(errorString))

安装

npm install modern-errors

如果使用任何插件,也必须安装它们。

npm install modern-errors-{插件名}

这个包同时适用于 Node.js >=18.18.0 和浏览器

这是一个 ES 模块。它必须使用 import 或 import() 语句加载,而不是 require()。如果使用 TypeScript,必须将其配置为输出 ES 模块,而不是 CommonJS。

使用方法

⛑️ 错误类

创建错误类

import ModernError from 'modern-errors'

export const BaseError = ModernError.subclass('BaseError')
export const UnknownError = BaseError.subclass('UnknownError')
export const InputError = BaseError.subclass('InputError')
export const AuthError = BaseError.subclass('AuthError')
export const DatabaseError = BaseError.subclass('DatabaseError')

导出错误类

导出并记录所有错误类允许使用者对其进行检查。这也使得在模块之间共享错误类成为可能。

检查错误类

if (error instanceof InputError) {
  // ...
}

错误子类

ErrorClass.subclass()返回一个子类。 父类的选项与其子类的选项合并。

export const BaseError = ModernError.subclass('BaseError', {
  props: { isError: true },
})
export const InputError = BaseError.subclass('InputError', {
  props: { isUserError: true },
})

const error = new InputError('...')
console.log(error.isError) // true
console.log(error.isUserError) // true
console.log(error instanceof BaseError) // true
console.log(error instanceof InputError) // true

🏷️ 错误属性

错误类属性

const InputError = BaseError.subclass('InputError', {
  props: { isUserError: true },
})
const error = new InputError('...')
console.log(error.isUserError) // true

错误实例属性

const error = new InputError('...', { props: { isUserError: true } })
console.log(error.isUserError) // true

内部错误属性

内部或秘密的错误属性可以用_作为前缀。这使它们成为不可枚举的,从而防止被迭代或记录。

const error = new InputError('...', {
  props: { userId: 6, _isUserError: true },
})
console.log(error.userId) // 6
console.log(error._isUserError) // true
console.log(Object.keys(error)) // ['userId']
console.log(error) // 记录`userId`,但不记录`_isUserError`

🎀 包装错误

抛出错误

throw new InputError('缺少文件路径。')

包装内部错误

任何错误的消息选项都可以使用标准cause选项进行包装。

内部错误不会被设置为cause属性,而是直接合并到外部错误中,包括其messagestacknameAggregateError.errors和任何附加属性

try {
  // ...
} catch (cause) {
  throw new InputError('无法读取文件。', { cause })
}

包装错误消息

外部错误消息会被追加,除非它为空。如果外部错误消息以::\n结尾,则会被前置。

const cause = new InputError('文件不存在。')
// InputError: 文件不存在。
throw new InputError('', { cause })
// InputError: 文件不存在。
// 无法读取文件。
throw new InputError('无法读取文件。', { cause })
// InputError: 无法读取文件:文件不存在。
throw new InputError(`无法读取文件:`, { cause })
// InputError: 无法读取文件:
// 文件不存在。
throw new InputError(`无法读取文件:\n`, { cause })

包装错误类

外部错误的类会替换内部错误的类。

try {
  throw new AuthError('...')
} catch (cause) {
  // 现在是InputError
  throw new InputError('...', { cause })
}

除非外部错误的类是父类,比如BaseError

try {
  throw new AuthError('...')
} catch (cause) {
  // 仍然是AuthError
  throw new BaseError('...', { cause })
}

包装错误选项

外部错误的props插件选项会被合并。

try {
  throw new AuthError('...', innerOptions)
} catch (cause) {
  // `outerOptions`与`innerOptions`合并
  throw new BaseError('...', { ...outerOptions, cause })
}

聚合错误

errors选项将多个错误聚合成一个。这类似于new AggregateError(errors),但适用于任何错误类。

const databaseError = new DatabaseError('...')
const authError = new AuthError('...')
throw new InputError('...', { errors: [databaseError, authError] })
// InputError: ... {
//   [errors]: [
//     DatabaseError: ...
//     AuthError: ...
//   ]
// }

🚨 规范化错误

包装的错误

任何错误都可以直接传递给causeerrors选项,即使它是无效的未知的或未规范化的

try {
  // ...
} catch (cause) {
  throw new InputError('...', { cause })
}

无效错误

操作不是Error实例或具有无效属性的错误可能导致意外的错误。 BaseError.normalize()可以解决这个问题。

try {
  throw '缺少文件路径。'
} catch (invalidError) {
  // 这会失败:`invalidError.message`是`undefined`
  console.log(invalidError.message.trim())
}
try {
  throw '缺少文件路径。'
} catch (invalidError) {
  const normalizedError = BaseError.normalize(invalidError)
  // 这样可以正常工作: '缺少文件路径。'
  // `normalizedError` 是 `BaseError` 的实例。
  console.log(normalizedError.message.trim())
}

🐞 未知错误

处理已知错误

已知错误应该在 try {} catch {} 块中处理,并用特定类包装。该块应该只覆盖可能抛出错误的语句,以防止捕获其他不相关的错误。

try {
  return regExp.test(value)
} catch (error) {
  // 现在是 `InputError` 实例
  throw new InputError('无效的正则表达式:', { cause: error })
}

标准化未知错误

如果错误没有按照上述方式处理,就被视为_未知_。这表示发生了意外异常,通常是一个bug。 BaseError.normalize(error, UnknownError)UnknownError 类分配给这些错误。

export const UnknownError = BaseError.subclass('UnknownError')
try {
  return regExp.test(value)
} catch (error) {
  // 现在是 `UnknownError` 实例
  throw BaseError.normalize(error, UnknownError)
}

顶级错误处理器

BaseError.normalize(error, UnknownError)包装模块的主要函数可以确保每个抛出的错误都是有效的,应用了插件,并且具有已知UnknownError类。

export const main = () => {
  try {
    // ...
  } catch (error) {
    throw BaseError.normalize(error, UnknownError)
  }
}

🔌 插件

插件列表

插件扩展了 modern-errors 的功能。所有可用的插件都列在这里

添加插件

要使用插件,请先安装它,然后将其传递给plugins 选项

npm install modern-errors-{pluginName}
import ModernError from 'modern-errors'

import modernErrorsBugs from 'modern-errors-bugs'
import modernErrorsSerialize from 'modern-errors-serialize'

export const BaseError = ModernError.subclass('BaseError', {
  plugins: [modernErrorsBugs, modernErrorsSerialize],
})
// ...

自定义插件

请查看以下文档以创建你自己的插件。

插件选项

大多数插件可以通过选项进行配置。选项的名称与插件相同。

const options = {
  // `modern-errors-bugs` 选项
  bugs: 'https://github.com/my-name/my-project/issues',
  // `props` 可以像插件选项一样配置和修改
  props: { userId: 5 },
}

插件选项可以应用于(按优先顺序):

export const BaseError = ModernError.subclass('BaseError', options)
export const InputError = BaseError.subclass('InputError', options)
throw new InputError('...', options)
  • 插件方法调用: 最后一个参数,仅传递该插件的选项
ErrorClass[methodName](...args, options[pluginName])
error[methodName](...args, options[pluginName])

🔧 自定义逻辑

custom 选项可用于为错误提供额外的方法、constructor、属性或选项。

export const InputError = BaseError.subclass('InputError', {
  // `class` 必须继承自父错误类
  custom: class extends BaseError {
    // 如果定义了 `constructor`,其参数必须是 (message, options)
    // 可以定义额外的 `options`。
    constructor(message, options) {
      message += options?.suffix ?? ''
      super(message, options)
    }

    isUserInput() {
      // ...
    }
  },
})

const error = new InputError('错误的用户名', { suffix: ': 示例' })
console.log(error.message) // '错误的用户名: 示例'
console.log(error.isUserInput())

🤓 TypeScript

请查看以下文档了解有关 TypeScript 类型的信息。

API

ModernError

顶级 ErrorClass

ErrorClass.subclass(name, options?)

name: string
options: ClassOptions?

创建并返回一个子 ErrorClass

options

options.props

类型: object

错误类属性

options.plugins

类型: Plugin[]

options.custom

类型: class extends ErrorClass {}

自定义类,用于添加任何方法、constructor 或属性。

options.*

任何插件选项也可以在此指定。

new ErrorClass(message, options?)

message: string
options: InstanceOptions?
返回值: Error

options

options.props

类型: object

错误实例属性

options.cause

类型: any

包装的内部错误。

options.errors

类型: any[]

聚合的错误数组。

options.*

任何插件选项也可以在此指定。

ErrorClass.normalize(error, NewErrorClass?)

error: Error | any
NewErrorClass: ErrorClass 的子类
返回值: Error

标准化无效错误

如果 error 的类是 ErrorClass 的子类,它将保持不变。 否则,它将被转换为 NewErrorClass,默认为 ErrorClass 本身。

模块

这个框架汇集了一系列可以单独使用的模块:

支持

如有任何问题,请_不要犹豫_在 GitHub 上提交问题

我们欢迎所有人,不论个人背景如何。我们执行行为准则以促进积极和包容的环境。

贡献

这个项目是用 ❤️ 制作的。回馈的最简单方式是给它加星并在网上分享。

如果文档不清楚或有错别字,请点击页面的编辑按钮(铅笔图标)并提出修改建议。

如果您想帮助我们修复错误或添加新功能,请查看我们的指南。欢迎提交拉取请求!

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号