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
161 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; });"
}
}
}
]
}