https://github.com/tauhidul0821/rxjs-pactice
https://github.com/tauhidul0821/rxjs-pactice
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/tauhidul0821/rxjs-pactice
- Owner: tauhidul0821
- Created: 2021-12-29T08:52:44.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-03-11T10:47:21.000Z (3 months ago)
- Last Synced: 2025-03-11T11:34:06.497Z (3 months ago)
- Language: JavaScript
- Size: 38.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# RxJS Features Explained
This document provides a clean and simple explanation of the RxJS features used in the project, along with examples for better understanding.
---
## **1. RxJS Classes & Subjects**
### **Observable**
An `Observable` is like a stream of data that you can listen to over time.
```typescript
import { Observable } from 'rxjs';const myObservable = new Observable((observer) => {
observer.next(1);
observer.next(2);
observer.complete(); // Signal that no more values will be emitted
});myObservable.subscribe((value) => console.log(value));
// Output: 1, 2
```### **Subject**
A `Subject` is like an `Observable`, but it can also emit values.
```typescript
import { Subject } from 'rxjs';const mySubject = new Subject();
mySubject.subscribe((value) => console.log('Subscriber 1:', value));
mySubject.subscribe((value) => console.log('Subscriber 2:', value));mySubject.next(10);
// Output:
// Subscriber 1: 10
// Subscriber 2: 10
```### **BehaviorSubject**
A `BehaviorSubject` holds a current value and emits the latest value to new subscribers.
```typescript
import { BehaviorSubject } from 'rxjs';const myBehaviorSubject = new BehaviorSubject(100);
myBehaviorSubject.subscribe((value) => console.log('Subscriber 1:', value));
myBehaviorSubject.next(200);
// Output: Subscriber 1: 100, Subscriber 1: 200myBehaviorSubject.subscribe((value) => console.log('Subscriber 2:', value));
// Output: Subscriber 2: 200 (gets the latest value immediately)
```---
## **2. RxJS Operators (Used to Modify Data Streams)**
### **switchMap**
Cancels the previous request and starts a new one when a new value is emitted.
```typescript
import { of, switchMap } from 'rxjs';of('User123').pipe(
switchMap((userId) => fetchUserData(userId))
).subscribe(console.log);function fetchUserData(id: string) {
return of(`Fetched data for ${id}`);
}
```### **tap**
Performs a side effect (like logging) without modifying the data.
```typescript
import { of, tap } from 'rxjs';of('Hello').pipe(
tap((value) => console.log('Before:', value))
).subscribe(console.log);// Output:
// Before: Hello
// After: Hello
```### **map**
Transforms each emitted value.
```typescript
import { of, map } from 'rxjs';of(2, 4, 6).pipe(
map((num) => num * 10)
).subscribe(console.log);// Output: 20, 40, 60
```### **mergeMap**
Flattens inner `Observable`s but does **not** cancel previous ones.
```typescript
import { of, mergeMap } from 'rxjs';of('User123').pipe(
mergeMap((userId) => fetchUserData(userId))
).subscribe(console.log);function fetchUserData(id: string) {
return of(`Fetched data for ${id}`);
}
```### **catchError**
Handles errors inside an `Observable`.
```typescript
import { of, throwError, catchError } from 'rxjs';throwError(() => new Error('Something went wrong')).pipe(
catchError((error) => of(`Handled Error: ${error.message}`))
).subscribe(console.log);// Output: Handled Error: Something went wrong
```---
## **3. Special Observables**
### **EMPTY**
An `Observable` that emits **nothing** and completes immediately.
```typescript
import { EMPTY } from 'rxjs';EMPTY.subscribe({
next: () => console.log('Next'),
complete: () => console.log('Completed')
});// Output: Completed
```---
## **4. Summary Table**
| Feature | Description |
|---------|-------------|
| **Observable** | Creates a stream of data |
| **Subject** | Observable that can emit values |
| **BehaviorSubject** | Holds the last emitted value |
| **switchMap** | Cancels previous observable and switches to a new one |
| **tap** | Executes side effects like logging |
| **map** | Transforms emitted values |
| **mergeMap** | Maps and flattens inner Observables |
| **catchError** | Catches and handles errors |
| **filter** | Filters emitted values |
| **debounceTime** | Delays emissions until no new values arrive within a time frame |
| **distinctUntilChanged** | Ignores consecutive duplicate values |
| **defaultIfEmpty** | Emits a default value if no data comes through |
| **finalize** | Executes code when an Observable completes or errors |
| **forkJoin** | Combines multiple Observables and waits for all to complete |
| **from** | Converts an array, promise, or iterable into an Observable |
| **of** | Creates an Observable from fixed values |
| **EMPTY** | Observable that emits nothing and completes immediately |---
## **Key RxJS Features and Functions**
### 1. **Core RxJS Concepts**
- **Observables**: The foundation of RxJS. Used to represent asynchronous data streams.
- **Subjects**: Special types of Observables that allow multicasting to multiple subscribers.
- `Subject`: A basic Subject that emits values to all subscribers.
- `BehaviorSubject`: A Subject that requires an initial value and emits the current value to new subscribers.
- **Operators**: Functions used to transform, filter, or combine Observables.
- **Subscriptions**: Used to listen to Observables and handle their emissions.---
### 2. **RxJS Operators Used in the Codebase**
#### **Creation Operators**
- **`of`**: Creates an Observable that emits a single value or a sequence of values.
```typescript
of([]) // Emits an empty array
```
- **`forkJoin`**: Combines multiple Observables and waits for all of them to complete before emitting a single array of their last values.
```typescript
forkJoin([observable1$, observable2$])
```
- **`Subject`**: Used to create a multicast Observable that can emit values to multiple subscribers.
```typescript
filterChange$ = new Subject();
```#### **Transformation Operators**
- **`map`**: Transforms the items emitted by an Observable by applying a function to each item.
```typescript
map((query) => ({ ...query, channelId: this.channel.id }))
```
- **`switchMap`**: Maps to a new Observable and switches to it, canceling the previous Observable.
```typescript
switchMap((query) => this.paidMediaService.getGraph(query))
```
- **`concatMap`**: Maps to a new Observable and processes them in sequence, one at a time.
```typescript
concatMap(({ node, query }) => this.paidMediaService.getHotels(node.key, query))
```
- **`tap`**: Used for side effects (e.g., logging, updating state) without modifying the stream.
```typescript
tap((response) => this.chartData = this.transformGraphData(response[0]))
```#### **Filtering Operators**
- **`filter`**: Emits only those items from the source Observable that satisfy a condition.
```typescript
filter((query) => !!(query.from && query.to))
```
- **`distinctUntilChanged`**: Emits only when the current value is different from the previous value.
```typescript
distinctUntilChanged()
```
- **`debounceTime`**: Emits a value only after a specified time has passed without another source emission.
```typescript
debounceTime(300) // Waits 300ms before emitting
```#### **Combination Operators**
- **`forkJoin`**: Combines multiple Observables and waits for all of them to complete before emitting a single array of their last values.
```typescript
forkJoin([observable1$, observable2$])
```#### **Error Handling Operators**
- **`catchError`**: Catches errors on the Observable and returns a new Observable or default value.
```typescript
catchError(() => of([])) // Returns an empty array on error
```#### **Utility Operators**
- **`takeUntilDestroyed`**: Automatically unsubscribes from an Observable when the component is destroyed (Angular-specific).
```typescript
takeUntilDestroyed()
```
- **`defaultIfEmpty`**: Emits a default value if the source Observable completes without emitting any values.
```typescript
defaultIfEmpty(null)
```---
### 3. **RxJS Patterns in the Codebase**
#### **Reactive Data Flow**
- **Filter Change Pattern**:
```typescript
filterChange$.next(filterQuery); // Emit new filter values
filterChange$
.pipe(
filter((query) => !!query),
switchMap((query) => this.service.getData(query))
)
.subscribe((data) => this.updateUI(data));
```#### **Dynamic Data Loading**
- **Expandable Tree Table**:
```typescript
loadHotels$
.pipe(
switchMap((node) => this.service.getHotels(node.key))
)
.subscribe((hotels) => this.updateTreeTable(hotels));
```#### **Error Handling**
- **Graceful Error Handling**:
```typescript
catchError(() => of([])) // Return empty array on error
```#### **Debounced Search**
- **Search with Debounce**:
```typescript
filterUser$
.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap((search) => this.service.search(search))
)
.subscribe((results) => this.updateResults(results));
```---
### 4. **RxJS Features Specific to Angular**
#### **Angular-Specific RxJS Functions**
- **`takeUntilDestroyed`**: Automatically unsubscribes from Observables when the component is destroyed (Angular 16+).
```typescript
takeUntilDestroyed()
```#### **Router Events**
- **Listening to Router Events**:
```typescript
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.router.url)
)
.subscribe((url) => this.updateTitle(url));
```---
### 5. **RxJS Functions to Learn**
Here’s a prioritized list of RxJS functions to learn based on their usage in the codebase:
#### **High Priority**
- `Subject`, `BehaviorSubject`
- `map`, `switchMap`, `concatMap`, `tap`
- `filter`, `distinctUntilChanged`, `debounceTime`
- `forkJoin`
- `catchError`
- `takeUntilDestroyed` (Angular-specific)#### **Medium Priority**
- `of`
- `defaultIfEmpty`
- `mergeMap` (not used here but common in RxJS)
- `combineLatest` (not used here but common in RxJS)#### **Low Priority**
- `throttleTime`, `auditTime` (for advanced timing control)
- `withLatestFrom` (for combining streams)---