Utilizing RxJS for Advanced Asynchronous Data Handling in Angular
Best practices for leveraging RxJS to manage complex asynchronous data streams and enhance application responsiveness.
0 likes
7 views
Rule Content
{ "title": "Utilizing RxJS for Advanced Asynchronous Data Handling in Angular", "description": "Best practices for leveraging RxJS to manage complex asynchronous data streams and enhance application responsiveness.", "category": "Angular Cursor Rules", "rules": [ { "id": "angular-rxjs-avoid-nested-subscriptions", "description": "Avoid nested subscriptions to maintain code readability and prevent potential memory leaks.", "severity": "error", "pattern": { "type": "call_expression", "callee": { "type": "member_expression", "object": { "type": "call_expression", "callee": { "type": "member_expression", "property": { "type": "identifier", "name": "subscribe" } } }, "property": { "type": "identifier", "name": "subscribe" } } }, "fix": { "description": "Refactor to use higher-order mapping operators like switchMap, mergeMap, or concatMap to flatten nested subscriptions.", "example": { "before": "this.service.getData().subscribe(data => { this.service.getMoreData(data.id).subscribe(moreData => { /* handle moreData */ }); });", "after": "this.service.getData().pipe(switchMap(data => this.service.getMoreData(data.id))).subscribe(moreData => { /* handle moreData */ });" } } }, { "id": "angular-rxjs-use-async-pipe", "description": "Use the async pipe in templates to automatically subscribe and unsubscribe from observables, preventing memory leaks.", "severity": "warning", "pattern": { "type": "call_expression", "callee": { "type": "member_expression", "property": { "type": "identifier", "name": "subscribe" } } }, "fix": { "description": "Replace manual subscription in the component with the async pipe in the template.", "example": { "before": "this.data$.subscribe(data => { this.data = data; });", "after": "<div *ngIf=\"data$ | async as data\">{{ data }}</div>" } } }, { "id": "angular-rxjs-manage-subscriptions", "description": "Ensure proper management of subscriptions to prevent memory leaks by unsubscribing when the component is destroyed.", "severity": "error", "pattern": { "type": "class_declaration", "body": { "type": "method_definition", "key": { "type": "identifier", "name": "ngOnDestroy" }, "value": { "type": "function_expression", "body": { "type": "block_statement", "body": [] } } } } }, { "id": "angular-rxjs-use-pipeable-operators", "description": "Use pipeable operators to enhance code readability and maintainability.", "severity": "warning", "pattern": { "type": "call_expression", "callee": { "type": "member_expression", "property": { "type": "identifier", "name": "map" } } }, "fix": { "description": "Refactor to use pipeable operators within the pipe method.", "example": { "before": "this.data$.map(data => data * 2).subscribe(result => { /* handle result */ });", "after": "this.data$.pipe(map(data => data * 2)).subscribe(result => { /* handle result */ });" } } }, { "id": "angular-rxjs-avoid-logic-in-subscribe", "description": "Avoid placing complex logic inside subscribe blocks to maintain code clarity and testability.", "severity": "warning", "pattern": { "type": "call_expression", "callee": { "type": "member_expression", "property": { "type": "identifier", "name": "subscribe" } }, "arguments": [ { "type": "function_expression", "body": { "type": "block_statement", "body": [ { "type": "expression_statement", "expression": { "type": "call_expression" } } ] } } ] }, "fix": { "description": "Move logic to RxJS operators before the subscribe method.", "example": { "before": "this.data$.subscribe(data => { const processedData = processData(data); this.result = processedData; });", "after": "this.data$.pipe(map(data => processData(data))).subscribe(processedData => { this.result = processedData; });" } } } ] }