modern-errors

modern-errors

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

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

错误处理异常封装错误类插件系统TypeScriptGithub开源项目
<picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ehmicky/design/main/modern-errors/modern-errors_dark.svg"/> <img alt="modern-errors 标志" src="https://yellow-cdn.veclightyear.com/835a84d5/909155bd-6d0c-4b60-b7be-0ebdd82184dd.svg" width="600"/> </picture>

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 上提交问题

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

贡献

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

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

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

<!-- 感谢我们出色的贡献者: --> <!-- ALL-CONTRIBUTORS-LIST:START --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <table> <tbody> <tr> <td align="center" valign="top" width="14.28%"><a href="https://fosstodon.org/@ehmicky"><img src="https://avatars2.githubusercontent.com/u/8136211?v=4?s=100" width="100px;" alt="ehmicky"/><br /><sub><b>ehmicky</b></sub></a><br /><a href="https://github.com/ehmicky/modern-errors/commits?author=ehmicky" title="代码">💻</a> <a href="#design-ehmicky" title="设计">🎨</a> <a href="#ideas-ehmicky" title="想法、规划与反馈">🤔</a> <a href="https://github.com/ehmicky/modern-errors/commits?author=ehmicky" title="文档">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/bhvngt"><img src="https://avatars.githubusercontent.com/u/79074469?v=4?s=100" width="100px;" alt="const_var"/><br /><sub><b>const_var</b></sub></a><br /><a href="#ideas-bhvngt" title="想法、规划与反馈">🤔</a> <a href="#question-bhvngt" title="回答问题">💬</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/abrenneke"><img src="https://avatars.githubusercontent.com/u/342540?v=4?s=100" width="100px;" alt="Andy Brenneke"/><br /><sub><b>Andy Brenneke</b></sub></a><br /><a href="#ideas-abrenneke" title="想法、规划与反馈">🤔</a> <a href="#question-abrenneke" title="回答问题">💬</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/tgfisher4"><img src="https://avatars.githubusercontent.com/u/49082176?v=4?s=100" width="100px;" alt="Graham Fisher"/><br /><sub><b>Graham Fisher</b></sub></a><br /><a href="https://github.com/ehmicky/modern-errors/issues?q=author%3Atgfisher4" title="错误报告">🐛</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/renzor-fist"><img src="https://avatars.githubusercontent.com/u/117486829?v=4?s=100" width="100px;" alt="renzor"/><br /><sub><b>renzor</b></sub></a><br /><a href="#question-renzor-fist" title="回答问题">💬</a> <a href="#ideas-renzor-fist" title="想法、规划与反馈">🤔</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/eugene1g"><img src="https://avatars.githubusercontent.com/u/147496?v=4?s=100" width="100px;" alt="Eugene"/><br /><sub><b>Eugene</b></sub></a><br /><a href="https://github.com/ehmicky/modern-errors/commits?author=eugene1g" title="代码">💻</a> <a href="https://github.com/ehmicky/modern-errors/issues?q=author%3Aeugene1g" title="错误报告">🐛</a></td> <td align="center" valign="top" width="14.28%"><a href="http://uk.linkedin.com/in/jonathanmarkchambers/"><img src="https://avatars.githubusercontent.com/u/49592?v=4?s=100" width="100px;" alt="Jonathan Chambers"/><br /><sub><b>Jonathan Chambers</b></sub></a><br /><a href="https://github.com/ehmicky/modern-errors/commits?author=jmchambers" title="测试">⚠️</a> <a href="https://github.com/ehmicky/modern-errors/issues?q=author%3Ajmchambers" title="错误报告">🐛</a></td> </tr> </tbody> </table> <!-- markdownlint-restore --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END -->

编辑推荐精选

博思AIPPT

博思AIPPT

AI一键生成PPT,就用博思AIPPT!

博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。

AI办公办公工具AI工具博思AIPPTAI生成PPT智能排版海量精品模板AI创作热门
潮际好麦

潮际好麦

AI赋能电商视觉革命,一站式智能商拍平台

潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。

iTerms

iTerms

企业专属的AI法律顾问

iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。

SimilarWeb流量提升

SimilarWeb流量提升

稳定高效的流量提升解决方案,助力品牌曝光

稳定高效的流量提升解决方案,助力品牌曝光

Sora2视频免费生成

Sora2视频免费生成

最新版Sora2模型免费使用,一键生成无水印视频

最新版Sora2模型免费使用,一键生成无水印视频

Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
商汤小浣熊

商汤小浣熊

最强AI数据分析助手

小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。

imini AI

imini AI

像人一样思考的AI智能体

imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。

下拉加载更多