首页/新闻资讯/正文详情

使用 NgRx ESLint 插件的 require-super-ondestroy 规则强制 ComponentStore 正确销毁

发布时间:2026/9/26 2:38:09 来源:云帆数科 栏目:资讯中心
使用 NgRx ESLint 插件的 require-super-ondestroy 规则强制 ComponentStore 正确销毁
前端状态管理【免费下载链接】platformReactive State for Angular项目地址https://gitcode.com/gh_mirrors/pl/platform点击查看免费下载本文围绕 NgRx ESLint 插件中的require-super-ondestroy规则展开讲解它为何要求所有继承ComponentStore并覆盖ngOnDestroy生命周期钩子的类必须调用super.ngOnDestroy()。阅读本文后你将理解该规则的判定原理、ComponentStore 销毁流程对资源清理的意义以及如何在 ESLint 平级配置flat config中启用和验证这一规则。规则定位与元信息require-super-ondestroy是 NgRx ESLint 插件面向ngrx/component-store模块提供的一条规则。官方规则文档projects/www/src/app/pages/guide/eslint-plugin/rules/require-super-ondestroy.md对其元信息定义如下类型Typeproblem即该规则标记的是会导致运行时问题的写法而非单纯的风格建议可自动修复FixableNo规则只报错不提供自动修复提供建议SuggestionNo需要类型检查Requires type checkingNo规则完全基于语法层面的 AST 结构判断不依赖 TypeScript 的类型信息可配置ConfigurableNo规则无任何额外选项开关即全部行为。规则的核心诉求可以概括为一句话任何继承ComponentStore的类如果覆盖override了ngOnDestroy生命周期钩子其方法体内部必须包含对super.ngOnDestroy()的调用以此确保ComponentStore自行管理的资源得到正确清理。为什么要强制调用 super.ngOnDestroy()这条规则并非空穴来风其依据直接来自ComponentStore的底层实现。查看 modules/component-store/src/component-store.ts 源码可以看到ComponentStore自身实现了OnDestroy接口并在内部维护了销毁相关的基础设施// ComponentStore 内部 private readonly destroySubject$ new ReplaySubjectvoid(1); readonly destroy$ this.destroySubject$.asObservable(); ngOnDestroy() { this.stateSubject$.complete(); this.destroySubject$.next(); }destroy$是一个暴露给所有子类使用的「生命周期结束信号」ComponentStore内部几乎所有长期订阅都通过takeUntil(this.destroy$)进行收尾——例如select派生的流、effect创建的订阅以及state信号底层对stateSubject$的订阅readonly state: SignalT toSignal( this.stateSubject$.pipe(takeUntil(this.destroy$)), { requireSync: false, manualCleanup: true } );effect方法的注释也明确写道其订阅「tied to the lifecycle of ComponentStore」通过.pipe(takeUntil(this.destroy$)).subscribe()与销毁信号绑定effect(generator) { const origin$ new Subject(); generator(origin$) .pipe(takeUntil(this.destroy$)) .subscribe(); // ... }关键问题在于ngOnDestroy只有被调用时destroySubject$.next()才会执行。如果你在子类中覆盖了ngOnDestroy却忘记调用super.ngOnDestroy()那么destroy$永远不会发出通知所有依赖takeUntil(this.destroy$)的 Observable 订阅、effect 流以及state信号背后的底层订阅都无法按时终止导致 Angular 组件已销毁后仍有流式资源泄漏进而可能引发内存泄漏与意外行为。这正是require-super-ondestroy把违规代码归类为problem问题而不是suggestion建议的根本原因。规则判定原理基于 AST 的结构化检测在 modules/eslint-plugin/src/rules/component-store/require-super-ondestroy.ts 中可以看到该规则借助createRule来自 modules/eslint-plugin/src/rule-creator.ts实现整体只做两层判断第一步确认导入了ComponentStore。规则监听ngrx/component-store的具名导入ImportDeclaration[source.valuengrx/component-store] ImportSpecifier[imported.nameComponentStore]() { hasNgrxComponentStoreImport true; }只有当源码真正从ngrx/component-store导入ComponentStore时后续检查才生效避免对无关代码产生误报。第二步用选择器定位违规的类方法。核心检查使用了一条复合选择器ClassDeclaration[superClass.nameComponentStore] ${ngOnDestroyMethodSelector}:not(:has(CallExpression[callee.object.typeSuper][callee.property.namengOnDestroy])) .key将其拆解ClassDeclaration[superClass.nameComponentStore]直接继承ComponentStore的类声明MethodDefinition[key.namengOnDestroy]类中存在名为ngOnDestroy的方法定义:not(:has(CallExpression[callee.object.typeSuper][callee.property.namengOnDestroy]))该方法体内不包含以super为调用对象、方法名为ngOnDestroy的调用表达式CallExpression .key命中后将报告位置指向方法名标识符。两条判断都满足且确实存在ngrx/component-store导入时规则便通过context.report抛出以下错误消息Call super.ngOnDestroy() inside a component stores ngOnDestroy method.值得强调的是这里的检测对象是调用表达式CallExpression。测试用例证实了几个容易被忽略的边界情况见 modules/eslint-plugin/spec/rules/component-store/require-super-ondestroy.spec.ts只写super.ngOnDestroy;引用方法但未调用会被判定为违规调用super.get()等其他super方法不算数仍会报错只有当类继承自名为ComponentStore的超类时才检查从非ngrx/component-store路径例如../components/component-store导入的同名类不会被该规则检查——测试用例中这一类写法被视作valid。错误示例与正确示例违规代码incorrect原文档给出的典型反例是在覆盖ngOnDestroy时只执行自定义清理逻辑Injectable() export class BooksStore extends ComponentStoreBooksState implements OnDestroy { // ... other BooksStore class members override ngOnDestroy(): void { this.cleanUp(); // custom cleanup logic } }此写法缺少super.ngOnDestroy()destroy$不会发出完成信号ComponentStore内部经takeUntil(this.destroy$)挂接的订阅无法释放规则会报告违规。合规代码correct正确做法是在自定义清理前后通常放在方法体末尾补上super.ngOnDestroy()Injectable() export class BooksStore extends ComponentStoreBooksState implements OnDestroy { // ... other BooksStore class members override ngOnDestroy(): void { this.cleanUp(); super.ngOnDestroy(); } }从测试用例的valid集合看规则的校验相当宽松只要求「方法体内存在一次super.ngOnDestroy()调用」对调用位置没有任何限制super.ngOnDestroy()单独存在即可通过this.cleanUp(); super.ngOnDestroy();通过super.ngOnDestroy(); this.cleanUp();同样通过this.cleanUp(); super.ngOnDestroy(); this.cleanUp();依旧通过。这意味着你可以根据自己的清理顺序偏好自由摆放super.ngOnDestroy()的位置规则关心的只是「有没有调用」这一事实。如何在项目中启用该规则require-super-ondestroy无需任何额外配置项启用方式有两种方式一使用预设配置推荐。该规则默认包含在组件存储的推荐预设中。在 modules/eslint-plugin/src/configs/component-store.ts 中可以看到预设将其设为errorrules: { ngrx/avoid-combining-component-store-selectors: error, ngrx/avoid-mapping-component-store-selectors: error, ngrx/require-super-ondestroy: error, ngrx/updater-explicit-return-type: error, },同时它也出现在 all.ts 与 all-type-checked.ts 这两个全量预设中。按照插件总览文档projects/www/src/app/pages/guide/eslint-plugin/index.md的 flat config 用法在eslint.config.js中引入即可const tseslint require(typescript-eslint); const ngrx require(ngrx/eslint-plugin); module.exports tseslint.config({ files: [**/*.ts], extends: [ // 只启用 component-store 相关规则 ...ngrx.configs.componentStore, ], });方式二单独覆盖规则。也可以在已有配置的rules字段中针对性地调整module.exports tseslint.config({ files: [**/*.ts], extends: [...ngrx.configs.all], rules: { ngrx/require-super-ondestroy: error, }, });由于该规则不需要类型信息因此无需在parserOptions中配置projectService之类的类型检查选项这使其在 lint 速度上具备天然优势——它是纯语法层的静态检查。测试验证与规则注册该规则的可靠性由一组针对性的单测保障。在 modules/eslint-plugin/spec/rules/component-store/require-super-ondestroy.spec.ts 中**valid 用例6 个**覆盖继承但不覆盖ngOnDestroy、覆盖且调用super.ngOnDestroy()、各种清理逻辑与super.ngOnDestroy()的排列组合、以及非ngrx/component-store导入的同名类**invalid 用例4 个**覆盖覆盖ngOnDestroy但方法体为空、只做自定义清理、写super.ngOnDestroy;而未调用、调用super.get()而非super.ngOnDestroy()。这些用例精确印证了上文所述的判定边界。规则本身通过 modules/eslint-plugin/src/rules/index.ts 注册为ngrx/require-super-ondestroy成为插件对外暴露的完整规则集的一员。小结require-super-ondestroy是 NgRx ESLint 插件中成本极低但价值明确的一条防护性规则它从语法层面杜绝「覆盖ngOnDestroy却绕过ComponentStore销毁逻辑」的常见疏漏。理解其背后的destroy$/takeUntil机制能让你在编写自定义清理逻辑时更清楚为什么必须保留super.ngOnDestroy()——那不只是「规则要求」而是保障响应式订阅被正确收尾、避免资源泄漏的关键一环。赞分享前端状态管理【免费下载链接】platformReactive State for Angular项目地址https://gitcode.com/gh_mirrors/pl/platform点击查看免费下载相关推荐ESLint constructor-super 规则详解强制派生类构造函数正确调用 super()ESLint constructor super 规则详解强制派生类构造函数正确调用 super 在 JavaScript 的类继承体系中派生类deriv开发工具Lint静态分析代码质量NgRx ESLint 规则深度解析updater-explicit-return-type 强制 ComponentStore Updater 显式声明返回类型NgRx ESLint 规则深度解析updater explicit return type 强制 ComponentStore Updater 显式声明返回前端状态管理游戏 DLSS 版本太旧怎么换DLSS Swapper 管理工具完整使用指南游戏 DLSS 版本太旧怎么换DLSS Swapper 管理工具完整使用指南 游戏发行了两三年帧率还过得去但质量模式下的重影很明显。翻进游戏目录一看内置桌面应用上一篇Paddle-Lite深度解析移动端AI推理引擎的架构设计与性能优化实战下一篇Catalyst数据管道详解如何高效处理多交易所的加密资产数据创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

使用 Megatron Bridge 在 SLURM + EFA 集群上运行 DeepSeek 预训练与 Nsys 性能剖析(pysheeet 实战指南)
使用 Megatron Bridge 在 SLURM + EFA 集群上运行 DeepSeek 预训练与 Nsys 性能剖析(pysheeet 实战指南)

文档教程开发工具 【免费下载链接】pysheeet Python Cheat Sheet 项目地址: https://gitcode.com/gh_mirrors/py/pysheeet 点击查看 免费下载 导读 本文基于 pysheeet 仓库 src/megatron 目录下的完整工具链,讲解如何用 Megatron Bridge 的 recipe 式接… · 2026/9/26 2:38:09

TensorFlow CNN水果识别毕业设计源码:从环境搭建到模型评估全流程
TensorFlow CNN水果识别毕业设计源码:从环境搭建到模型评估全流程

简介:这份资源是面向计算机相关专业毕业设计学生与希望提升工程能力的开发者的一套TensorFlow卷积神经网络水果图像识别项目源码,难度定位中等,适合作为课程设计、期末项目或毕业设计参考。压缩包共1058个文件,约79.95MB&#xff… · 2026/9/26 2:38:03

从OpenClaw到AiPy:省心部署AI代理的实战经验
从OpenClaw到AiPy:省心部署AI代理的实战经验

用过 OpenClaw 才知道:AiPy 才是真・省心神器先说说我的背景。我算是 AI 代理(Agent)工具的深度用户,从去年开始就把各种自动化任务往这类工具上迁移。最初选择 OpenClaw,是被它“一个框架连接所有渠道”的宣传吸引——… · 2026/9/26 2:38:03

从机器码到计算边界:AI大模型与Agent能力的真相
从机器码到计算边界:AI大模型与Agent能力的真相

前阵子看到一个访谈片段,斯蒂芬沃尔弗拉姆在被问到怎么看当前这波AI浪潮时,笑着说了句:“没有任何AI真正震撼我。”很多人的第一反应是“这人是不是对AI有什么误解”,但你要是把这句话放在他四十年研究计算宇宙的背景里再去琢磨&a… · 2026/9/26 3:18:09

光伏发电预测与LSTM:Python实现完整指南
光伏发电预测与LSTM:Python实现完整指南

简介:基于LSTM神经网络的光伏发电预测Python实现,是一套面向本科毕业设计与深度学习实践项目的完整方案,聚焦光伏发电功率的短期时间序列预测问题。项目内含可直接运行的Python源码、Jupyter Notebook过程分析文档、经过清洗与预处理的逐时光… · 2026/9/26 3:18:09

B站收藏失效视频找回指南:缓存提取与存档查询实战
B站收藏失效视频找回指南:缓存提取与存档查询实战

1. 收藏夹灰掉那一刻,我决定把这事彻底搞明白B站收藏夹里躺着几百个视频,某天点进去一看,一排排灰色封面整整齐齐,点开就提示“视频已失效”或者“稿件不可见”。那种感觉就像你精心整理的书架,某天回家发现一半的书被… · 2026/9/26 3:18:09

CLI-Anything:用自然语言安全驱动命令行的AI终端助手
CLI-Anything:用自然语言安全驱动命令行的AI终端助手

CLI-Anything:让命令行真正成为“Anything”的那层万能胶如果你跟我一样,每天要在七八台服务器之间来回切,手头至少有十几个项目的部署、巡检、日志排查任务,大概率也会有这种瞬间:明明上周刚用过某条find组合命令&… · 2026/9/26 3:18:03

React性能优化:shouldComponentUpdate与memo实战
React性能优化:shouldComponentUpdate与memo实战

相信不少React开发者都有过这样的经历:父组件里一个很普通的状态更新,比如拖动一下侧边栏、改一次筛选条件、刷新一下某个计数,屏幕上的整个列表、每个卡片、每行数据全都跟着重新渲染了一遍。数据量小的时候还能忍,一旦列表几百上… · 2026/9/26 3:18:03

gsd-core 修复 gsd-code-fixer 同分支检出冲突:基于 `git worktree add -b` 的 gsd-reviewfix 隔离分支机制
gsd-core 修复 gsd-code-fixer 同分支检出冲突:基于 `git worktree add -b` 的 gsd-reviewfix 隔离分支机制

【免费下载链接】gsd-core Git. Ship. Done - Core 项目地址: https://gitcode.com/gh_mirrors/ge/gsd-core 点击查看 免费下载 导读 本文剖析 gsd-core 中 PR #2990 的一次关键缺陷修复:gsd-code-fixer 代理在工作树(worktree)… · 2026/9/26 3:18:03

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码