ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Angular Core 运行时错误机制解析:从 errors.api.md 读懂 RuntimeError 与错误码体系

Angular Core 运行时错误机制解析:从 errors.api.md 读懂 RuntimeError 与错误码体系 Angular Core 运行时错误机制解析从 errors.api.md 读懂 RuntimeError 与错误码体系【免费下载链接】angularDeliver web apps with confidence 项目地址: https://gitcode.com/GitHub_Trending/an/angular导读本文以 Angular 仓库中由 API Extractor 生成的公开 API 报告 goldens/public-api/core/errors.api.md 为主体系统拆解 Angularangular/core包运行时错误处理机制的完整骨架RuntimeError错误类、formatRuntimeError/formatRuntimeErrorCode格式化函数以及包含近百个错误码的RuntimeErrorCode枚举。读者读完本文后将能够准确解读浏览器控制台中形如NG0200: ...、NG0500: ...的错误编号含义、掌握负号错误码与错误详情页之间的映射规则理解各功能域变更检测、依赖注入、模板、水合、信号等的错误码区间划分并学会在自己的开发与排错过程中快速定位对应源码与使用方式。一、errors.api.md 是什么一份由构建生成的 API 契约goldens/public-api/core/errors.api.md是 Angular 通过 API Extractor 生成的API 报告文件golden file其文件头明确声明Do not edit this file. It is a report generated by API Extractor.它的作用主要有三点公共 API 边界声明精确记录angular/core对外暴露的错误相关符号及其签名防止贡献者在重构时无意破坏公共 API 的稳定性类型契约快照任何对RuntimeError、formatRuntimeError、formatRuntimeErrorCode或RuntimeErrorCode的签名变更都会在 CI 中被 golden 测试捕获权威参考清单为开发者提供一份官方认可的错误码全集是排查运行时错误的索引表。报告中声明的全部公共符号只有四个但错误码枚举本身构成了这份文档的绝大部分价值符号类型说明formatRuntimeErrorT extends number RuntimeErrorCode函数将错误码与消息格式化为标准错误文本formatRuntimeErrorCodeT extends number RuntimeErrorCode函数将数字错误码转换为NG0xxx格式字符串RuntimeErrorT extends number RuntimeErrorCode类运行时错误对象继承自原生Error携带结构化codeRuntimeErrorCodeconst enum全部运行时错误码的常量枚举对应实现位于 packages/core/src/errors.ts下面逐层解读。二、RuntimeError 类统一错误格式的基石2.1 类签名与构造函数依据 errors.api.md 的声明// public export class RuntimeErrorT extends number RuntimeErrorCode extends Error { constructor(code: T, message: null | false | string); // (undocumented) code: T; }其源码实现在 packages/core/src/errors.ts#L181-L188export class RuntimeErrorT extends number RuntimeErrorCode extends Error { constructor( public code: T, message: null | false | string, ) { super(formatRuntimeErrorT(code, message)); } }几个值得注意的设计细节泛型参数T extends number RuntimeErrorCode默认约束为RuntimeErrorCode枚举使error.code具备完整的类型提示message的三态类型null | false | string。在开发模式ngDevMode开启下传入描述性字符串在生产构建经 tree-shaking 后message会退化为false从而在产物中抹去描述信息仅保留错误码code是公开只读属性可直接通过error.code拿到数字错误码用于程序化判断与上报。2.2 官方使用示例errors.ts的类注释给出了标准抛错范式throw new RuntimeError( RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED, ngDevMode Injector has already been destroyed.);2.3 仓库内的真实调用场景RuntimeError遍布核心运行时各模块以下是 packages/core/src/application/application_ref.ts 中的两处代表性用法递归 tick 检测application_ref.ts#L554-L562private tickImpl (): void { (typeof ngDevMode undefined || ngDevMode) warnIfDestroyed(this._destroyed); if (this._runningTick) { profiler(ProfilerEvent.ChangeDetectionEnd); throw new RuntimeError( RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK, ngDevMode ApplicationRef.tick is called recursively, ); } // ... };无限变更检测保护application_ref.ts#L603-L611if ((typeof ngDevMode undefined || ngDevMode) runs MAXIMUM_REFRESH_RERUNS) { throw new RuntimeError( RuntimeErrorCode.INFINITE_CHANGE_DETECTION, ngDevMode Infinite change detection while refreshing application views. Ensure views are not calling markForCheck on every template execution or that afterRender hooks always mark views for check., ); }再如信号输入缺省值检查packages/core/src/authoring/input/input_signal.ts#L137throw new RuntimeError(RuntimeErrorCode.REQUIRED_INPUT_NO_VALUE, message);从这些调用可以看出统一模式枚举错误码 ngDevMode 短路写法这既是错误机制的约定用法也是生产包体积优化的关键——开发信息随 tree-shaking 被剥离。三、错误码格式化NG0xxx 的生成规则formatRuntimeErrorCode与formatRuntimeError的实现位于 packages/core/src/errors.ts#L190-L215export function formatRuntimeErrorCodeT extends number RuntimeErrorCode(code: T): string { // Error code might be a negative number, which is a special marker that instructs the logic to // generate a link to the error details page on angular.io. // We also prepend 0 to non-compile-time errors. return NG0${Math.abs(code)}; } export function formatRuntimeErrorT extends number RuntimeErrorCode( code: T, message: null | false | string, ): string { const fullCode formatRuntimeErrorCode(code); let errorMessage ${fullCode}${message ? : message : }; if (ngDevMode code 0) { const addPeriodSeparator !errorMessage.match(/[.,;!?\n]$/); const separator addPeriodSeparator ? . : ; errorMessage ${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}; } return errorMessage; }3.1 规则拆解统一前缀NG0无论错误码是100还是-500最终展示为NG0100、NG0500。0是core 包在整体错误码空间中的标识编译期错误与运行时错误通过NG0区分见源码注释 We also prepend0to non-compile-time errors负号是有详情页的标记Math.abs(code)意味着负数仅用于编码语义不影响展示数字。errors.ts头部注释明确说明负号表示该错误码在 angular.io 上有专门的问题排查指南这是为了避免在运行时额外维护一份有指南的错误码集合而做的编码技巧详情页拼接仅在ngDevMode且code 0时错误消息末尾追加Find more at base/fullCode例如NG0500对应.../errors/NG0500标点感知通过正则判断消息末尾是否已有句号、逗号、分号、感叹号、问号或换行避免重复加点。3.2 详情页基址的动态推导ERROR_DETAILS_PAGE_BASE_URL定义于 packages/core/src/error_details_base_url.ts其上游DOC_PAGE_BASE_URL会根据当前版本动态决定域名前缀const full VERSION.full; const isPreRelease full.includes(-next) || full.includes(-rc) || full 0.0.0 -PLACEHOLDER; const prefix isPreRelease ? next : v${VERSION.major}; return https://${prefix}.angular.dev;即预发布版本-next/-rc链接指向next.angular.dev正式版指向v主版本号.angular.dev。这样错误详情页始终与开发者所用的 Angular 版本语义对齐。四、RuntimeErrorCode 全集按功能域划分的错误码区间errors.api.md 的核心价值在于完整罗列了RuntimeErrorCode枚举。其源码 packages/core/src/errors.ts#L31-L163 按功能域分组注释core 包保留错误码区间为 100–999并约定各包的区间如下包错误码区间core100–999forms1000–1999common2000–2999animations3000–3999router4000–4999platform-browser5000–5500service-worker5600–5699platform-server5700–5800下面按源码分组逐一列出全部枚举项与 golden 文件一一对应。4.1 变更检测Change Detection Errors错误码常量数值EXPRESSION_CHANGED_AFTER_CHECKED-100RECURSIVE_APPLICATION_REF_TICK101INFINITE_CHANGE_DETECTION103其中RECURSIVE_APPLICATION_REF_TICKNG0101对应上文tickImpl中的递归保护INFINITE_CHANGE_DETECTIONNG0103对应synchronize()中刷新轮次超限见 application_ref.ts#L588-L612。4.2 依赖注入Dependency Injection Errors错误码常量数值CYCLIC_DI_DEPENDENCY-200PROVIDER_NOT_FOUND-201INVALID_FACTORY_DEPENDENCY202MISSING_INJECTION_CONTEXT-203INVALID_INJECTION_TOKEN-204INJECTOR_ALREADY_DESTROYED-205PROVIDER_IN_WRONG_CONTEXT-207MISSING_INJECTION_TOKEN208INVALID_MULTI_PROVIDER-209MISSING_DOCUMENT210INVALID_APP_ID211INJECTOR_ALREADY_DESTROYEDNG0205正是RuntimeError类注释中的示例错误码INVALID_MULTI_PROVIDERNG0209在 application_ref.ts#L749-L751 的 provider 校验路径中被抛出。4.3 模板Template Errors错误码常量数值MULTIPLE_COMPONENTS_MATCH-300EXPORT_NOT_FOUND-301PIPE_NOT_FOUND-302UNKNOWN_BINDING303UNKNOWN_ELEMENT304TEMPLATE_STRUCTURE_ERROR305INVALID_EVENT_BINDING306HOST_DIRECTIVE_UNRESOLVABLE307HOST_DIRECTIVE_NOT_STANDALONE308DUPLICATE_DIRECTIVE309HOST_DIRECTIVE_COMPONENT310HOST_DIRECTIVE_UNDEFINED_BINDING311HOST_DIRECTIVE_CONFLICTING_ALIAS312MULTIPLE_MATCHING_PIPES313UNINITIALIZED_LET_ACCESS314NO_BINDING_TARGET315INVALID_BINDING_TARGET316INVALID_SET_INPUT_CALL317INVALID_STYLE_PROP_VALUE-318从数值序列可看出模板错误是当前占用码位最多、增长最快的分组其中 300–318 区间还密集覆盖了宿主指令host directive各类非法组合。4.4 应用启动Bootstrap Errors错误码常量数值MULTIPLE_PLATFORMS400PLATFORM_NOT_FOUND-401MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP402BOOTSTRAP_COMPONENTS_NOT_FOUND-403PLATFORM_ALREADY_DESTROYED404ASYNC_INITIALIZERS_STILL_RUNNING405APPLICATION_REF_ALREADY_DESTROYED406RENDERER_NOT_FOUND407PROVIDED_BOTH_ZONE_AND_ZONELESS408ASYNC_INITIALIZERS_STILL_RUNNINGNG0405与APPLICATION_REF_ALREADY_DESTROYEDNG0406均在 application_ref.ts 中被抛出分别见第 482 行与第 799-800 行PROVIDED_BOTH_ZONE_AND_ZONELESSNG0408则对应 Zone.js 与 zoneless 混用的配置冲突检测。4.5 水合Hydration Errors错误码常量数值HYDRATION_NODE_MISMATCH-500HYDRATION_MISSING_SIBLINGS-501HYDRATION_MISSING_NODE-502UNSUPPORTED_PROJECTION_DOM_NODES-503INVALID_SKIP_HYDRATION_HOST-504MISSING_HYDRATION_ANNOTATIONS-505HYDRATION_STABLE_TIMEDOUT-506MISSING_SSR_CONTENT_INTEGRITY_MARKER-507MISCONFIGURED_INCREMENTAL_HYDRATION508HYDRATION_MISSING_NODE_ON_PATH509PARENT_NODE_NOT_FOUND510这是 SSR 场景最常见的错误家族全部集中在 500–510 区间。水合实现位于 packages/core/src/hydration其中 hydrations/utils.ts 与 hydrations/api.ts 均直接引用了formatRuntimeError来格式化这些错误。4.6 信号Signal Errors错误码常量数值SIGNAL_WRITE_FROM_ILLEGAL_CONTEXT600REQUIRE_SYNC_WITHOUT_SYNC_EMIT601ASSERTION_NOT_INSIDE_REACTIVE_CONTEXT-602SIGNAL_WRITE_FROM_ILLEGAL_CONTEXTNG0600的抛出点在 application_ref.ts#L83用于禁止在非法的响应式上下文如模板执行期外中写信号。4.7 动画、i18n、Defer 与 Standalone分组错误码常量数值动画ANIMATE_INVALID_VALUE650i18nINVALID_I18N_STRUCTURE700i18nMISSING_LOCALE_DATA701Defer750–799 区间DEFER_LOADING_FAILED-750DeferDEFER_IN_HMR_MODE-751StandaloneIMPORT_PROVIDERS_FROM_STANDALONE800DEFER_LOADING_FAILEDNG0750在 packages/core/src/defer/instructions.ts 的defer块加载失败路径中抛出。4.8 JIT 编译与运行时杂项900–923错误码常量数值INVALID_DIFFER_INPUT900NO_SUPPORTING_DIFFER_FACTORY901VIEW_ALREADY_ATTACHED902INVALID_INHERITANCE903UNSAFE_VALUE_IN_RESOURCE_URL904UNSAFE_VALUE_IN_SCRIPT905MISSING_GENERATED_DEF906TYPE_IS_NOT_STANDALONE907MISSING_ZONEJS908UNEXPECTED_ZONE_STATE909UNSAFE_ATTRIBUTE_BINDING-910VIEW_ALREADY_DESTROYED911COMPONENT_ID_COLLISION-912IMAGE_PERFORMANCE_WARNING-913UNEXPECTED_ZONEJS_PRESENT_IN_ZONELESS_MODE914MISSING_NG_MODULE_DEFINITION915MISSING_DIRECTIVE_DEFINITION916EXTERNAL_RESOURCE_LOADING_FAILED918DEF_TYPE_UNDEFINED-919NG_MODULE_ID_NOT_FOUND920DUPLICATE_NG_MODULE_ID921VIEW_DESTROYED_INSERT_ERROR922VIEW_DESTROYED_MOVE_ERROR923注意码位917 已被移除源码中以/* 917 - Removed */注释保留占位避免历史错误码复用造成的歧义。安全相关错误UNSAFE_VALUE_IN_RESOURCE_URLNG0904、UNSAFE_VALUE_IN_SCRIPTNG0905、UNSAFE_ATTRIBUTE_BINDINGNG0910构成 XSS 防护体系的一环对应文档基址常量旁的XSS_SECURITY_URL见 error_details_base_url.ts#L35-L36。4.9 信号集成、Output 与 Repeater950–956分组错误码常量数值信号集成REQUIRED_INPUT_NO_VALUE-950信号集成REQUIRED_QUERY_NO_VALUE-951信号集成REQUIRED_MODEL_NO_VALUE952OutputOUTPUT_REF_DESTROYED953RepeaterLOOP_TRACK_DUPLICATE_KEYS-955RepeaterLOOP_TRACK_RECREATE-956REQUIRED_INPUT_NO_VALUENG0950由input.required()缺失绑定触发抛出点在 input_signal.ts#L137LOOP_TRACK_DUPLICATE_KEYSNG0955与LOOP_TRACK_RECREATENG0956由for循环的track表达式冲突触发实现在 packages/core/src/render3/list_reconciliation.ts。4.10 运行时依赖追踪与 resource() API980–992分组错误码常量数值运行时依赖追踪RUNTIME_DEPS_INVALID_IMPORTED_TYPE980运行时依赖追踪RUNTIME_DEPS_ORPHAN_COMPONENT981resource()MUST_PROVIDE_STREAM_OPTION990resource()RESOURCE_COMPLETED_BEFORE_PRODUCING_VALUE-991resource()INVALID_RESOURCE_CREATION_IN_PARAMS992这一区间是最新加入的对应新版resource()API 与运行时依赖追踪runtime dependency tracker功能。至此 core 包错误码用满至 999 上限源码注释 Upper bounds for core runtime errors is 999。五、错误码语义速查正负号与区间解读指南5.1 负号 有官方错误指南这是理解 Angular 错误输出的最重要规则。errors.ts头部注释packages/core/src/errors.ts#L11-L30明确说明the minus sign denotes the fact that a particular code has a detailed guide on angular.io.因此当你在开发模式看到类似NG0500: ... Find more at .../errors/NG0500时说明该错误有官方深度排查文档反之正数错误码如 NG0101、NG0208通常只有代码内消息没有独立详情页。5.2 功能域优先定位法排查线上错误时可按区间快速缩小范围NG0-1xx变更检测NG0-2xx依赖注入NG0-3xx模板与宿主指令NG0-4xx应用启动与平台生命周期NG0-5xxSSR 水合NG0-6xx信号与动画NG0-7xxi18n 与deferNG0-8xxstandaloneNG0-9xxJIT、安全、信号集成、for与resource()。再结合 errors.api.md 中的常量名即可在仓库内全局搜索对应抛错点。六、如何在业务代码中复用这套机制虽然RuntimeError主要服务于框架内部但理解其设计对编写可维护的库与业务代码同样有借鉴意义用枚举管理错误码所有错误码集中定义、按域分组、预留区间避免魔法数字负号编码附加信息把是否有详情文档这类元信息编码进错误码本身省去运行时维护额外集合的成本ngDevMode message写法开发时保留完整描述生产构建自动剥离兼顾可调试性与包体积统一格式化入口通过formatRuntimeError保证所有错误输出格式一致NG0xxx: message并自动附带文档链接。若需在框架外部判断错误类型可读取RuntimeError实例的code属性例如try { // 触发变更检测相关操作 } catch (error) { if (error instanceof RuntimeError) { switch (error.code) { case RuntimeErrorCode.INFINITE_CHANGE_DETECTION: // 处理无限变更检测 break; // ... } } }七、延伸阅读路径goldens/public-api/core/errors.api.md本文依据的公开 API 报告错误码权威清单packages/core/src/errors.tsRuntimeError、formatRuntimeError、formatRuntimeErrorCode与RuntimeErrorCode的完整实现及分组注释packages/core/src/error_details_base_url.ts错误详情页基址与 XSS 文档地址的动态推导逻辑packages/core/src/application/application_ref.tsRECURSIVE_APPLICATION_REF_TICK、INFINITE_CHANGE_DETECTION等错误码的真实抛错场景packages/core/src/authoring/input/input_signal.tsREQUIRED_INPUT_NO_VALUE的触发实现packages/core/src/render3/list_reconciliation.tsfor循环 track 冲突错误码NG0955/NG0956的实现位置。掌握这份错误码索引就等于拿到了一张 Angular Core 运行时故障地图看到控制台中的NG0xxx即可从本文的区间表、符号名直达对应源码快速定位问题根因。【免费下载链接】angularDeliver web apps with confidence 项目地址: https://gitcode.com/GitHub_Trending/an/angular创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表