拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

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

使用 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),仅供参考
返回列表