Anti-pattern Avoidance Checklist
Use this checklist to ensure your RxJS code does not fall into any anti-patterns. Click on each item to see detailed explanations and code examples.
Checklist Items
🔴 Avoid Critical Problems
| Check | Item | Key Points |
|---|---|---|
| Publish Subject with asObservable() | Do not export Subject directly, publish it as an Observable with asObservable()Allow state changes only through dedicated methods | |
| Avoid nested subscribe | Do not call another subscribe within subscribeFlatten with switchMap, mergeMap, concatMap, etc. | |
| Always unsubscribe from infinite streams | Always unsubscribe from infinite streams like event listenerstakeUntil pattern or Subscription management | |
| Explicitly configure shareReplay | Use the form shareReplay({ bufferSize: 1, refCount: true })Enable reference counting to prevent memory leaks | |
| Avoid nested if statements within subscribe | Avoid complex conditional branching (3 or more nested levels) within subscribeWrite declaratively with operators like filter, iif, partition |
🟡 Avoid Problems Requiring Attention
| Check | Item | Key Points |
|---|---|---|
| map is pure function, side effects in tap | Do not change state or output logs within mapExplicitly separate side effects with tap operator | |
| Use Cold/Hot appropriately | Convert HTTP requests to Hot with shareReplayDetermine whether execution should happen per subscription or be shared | |
| Convert Promise with from | Do not mix Promise and Observable Convert to Observable with from() for unified processing | |
| Control high-frequency events | Control search input with debounceTime, scrolling with throttleTimeExclude duplicates with distinctUntilChanged |
🔵 Improve Code Quality
| Check | Item | Key Points |
|---|---|---|
| Handle errors appropriately | Catch errors with catchError and handle appropriatelyDisplay user-friendly error messages Retry with retry / retryWhen as needed | |
| Properly release DOM events | Always unsubscribe from fromEvent subscriptionsAutomatically unsubscribe with takeUntil when component is destroyed | |
| Ensure type safety | Define interfaces and type aliases Explicitly specify Observable<T> type parametersLeverage TypeScript type inference | |
| Choose appropriate operators | Search: switchMap, parallel: mergeMapSequential: concatMap, prevent double-click: exhaustMap | |
| Simple processing doesn't need RxJS | Regular JavaScript is sufficient for array processing, etc. Use RxJS for asynchronous processing and event streams | |
| Manage state reactively | Manage state with BehaviorSubject or scanUse subscribe as final trigger | |
| Write tests | Implement marble testing with TestSchedulerMake asynchronous processing testable synchronously |
How to Use
1. During Code Review
After writing new code, conduct a self-review using this checklist.
2. During Pull Requests
Include this checklist in your pull request template so reviewers can verify with common criteria.
3. Regular Reviews
Use this checklist regularly against your existing codebase to check for anti-patterns.
4. Share Within Team
Share with team members to unify RxJS best practices.
Related Resources
- Common Mistakes and How to Fix Them - Detailed explanations and code examples for each anti-pattern
- Anti-Patterns Collection Top - List of anti-patterns and how to learn
- Error Handling - Error handling best practices
- Testing Techniques - How to test RxJS code
Tips for Using the Checklist
Don't try to perfect all items at once
- First, prioritize critical problems (🔴)
- Improve step by step
Set priorities within the team
- Adjust importance according to project characteristics
- Create customized checklists
Consider automation
- Automate checks with static analysis tools like ESLint
- Integrate into CI/CD pipeline
Regular updates
- Update according to RxJS version upgrades
- Reflect insights from team experience
Important: This checklist is not for writing perfect code, but a guide to avoid common problems. Use it flexibly according to your project context.