Opérateurs RxJS
Creation Operators
Section intitulée « Creation Operators »import { of, from, interval, timer, fromEvent } from 'rxjs';
// of - emit values in sequenceof(1, 2, 3).subscribe(x => console.log(x)); // 1, 2, 3
// from - convertir tableau/promise en observablefrom([1, 2, 3]).subscribe(x => console.log(x));from(fetch('/api/data')).subscribe(response => console.log(response));
// interval - emit every N millisecondsinterval(1000).subscribe(x => console.log(x)); // 0, 1, 2, 3...
// timer - emit after delay, then intervaltimer(3000, 1000).subscribe(x => console.log(x)); // Wait 3s, then emit every 1s
// fromEvent - convertir event en observableconst clicks$ = fromEvent(document, 'click');clicks$.subscribe(event => console.log(event));Transformation Operators
Section intitulée « Transformation Operators »import { map, pluck, mapTo, scan } from 'rxjs/operators';
// map - transform each valueof(1, 2, 3).pipe( map(x => x * 2)).subscribe(x => console.log(x)); // 2, 4, 6
// mapTo - mapper vers une valeur constanteclicks$.pipe( mapTo(1)).subscribe(x => console.log(x)); // 1, 1, 1...
// scan - accumulate values (like reduce)of(1, 2, 3).pipe( scan((acc, value) => acc + value, 0)).subscribe(x => console.log(x)); // 1, 3, 6Filtering Operators
Section intitulée « Filtering Operators »import { filter, take, takeUntil, takeWhile, skip, distinct, debounceTime } from 'rxjs/operators';
// filter - emit only values that pass conditionof(1, 2, 3, 4, 5).pipe( filter(x => x % 2 === 0)).subscribe(x => console.log(x)); // 2, 4
// take - take first N valuesof(1, 2, 3, 4, 5).pipe( take(3)).subscribe(x => console.log(x)); // 1, 2, 3
// takeUntil - take until another observable emitsconst stop$ = new Subject();interval(1000).pipe( takeUntil(stop$)).subscribe(x => console.log(x));
// takeWhile - take while condition is trueof(1, 2, 3, 4, 5).pipe( takeWhile(x => x < 4)).subscribe(x => console.log(x)); // 1, 2, 3
// skip - skip first N valuesof(1, 2, 3, 4, 5).pipe( skip(2)).subscribe(x => console.log(x)); // 3, 4, 5
// distinct - emit only unique valuesof(1, 1, 2, 2, 3).pipe( distinct()).subscribe(x => console.log(x)); // 1, 2, 3
// debounceTime - emit after silence periodsearchInput$.pipe( debounceTime(300)).subscribe(value => this.search(value));Combination Operators
Section intitulée « Combination Operators »import { merge, concat, combineLatest, forkJoin, zip } from 'rxjs';import { mergeMap, concatMap, switchMap, exhaustMap } from 'rxjs/operators';
// merge - emit values from multiple observablesmerge( of(1, 2, 3), of(4, 5, 6)).subscribe(x => console.log(x)); // 1, 2, 3, 4, 5, 6
// concat - emit one observable after anotherconcat( of(1, 2, 3), of(4, 5, 6)).subscribe(x => console.log(x)); // 1, 2, 3, 4, 5, 6
// combineLatest - emit when any observable emitscombineLatest([ of('A', 'B'), of(1, 2)]).subscribe(([letter, number]) => { console.log(letter, number); // B 1, B 2});
// forkJoin - attendre que toutes les requêtes soient terminéesforkJoin({ users: this.http.get('/users'), posts: this.http.get('/posts')}).subscribe(({ users, posts }) => { console.log(users, posts);});
// zip - combine values by indexzip( of('A', 'B', 'C'), of(1, 2, 3)).subscribe(([letter, number]) => { console.log(letter, number); // A 1, B 2, C 3});Flattening Operators
Section intitulée « Flattening Operators »// switchMap - annuler le précédent, passer au nouvel observablesearchTerm$.pipe( debounceTime(300), switchMap(term => this.http.get(`/search?q=${term}`))).subscribe(results => console.log(results));
// mergeMap - run all concurrentlyusers$.pipe( mergeMap(user => this.http.get(`/posts/${user.id}`))).subscribe(posts => console.log(posts));
// concatMap - run sequentiallyrequests$.pipe( concatMap(req => this.http.post('/api', req))).subscribe(response => console.log(response));
// exhaustMap - ignore new values while current is activesaveButton$.pipe( exhaustMap(() => this.http.post('/save', data))).subscribe(response => console.log(response));Error Handling
Section intitulée « Error Handling »import { catchError, retry, retryWhen, throwError } from 'rxjs';
// catchError - handle errorsthis.http.get('/api/data').pipe( catchError(error => { console.error('Error:', error); return of([]); // Return fallback value })).subscribe(data => console.log(data));
// retry - retry N times on errorthis.http.get('/api/data').pipe( retry(3), catchError(error => throwError(() => error))).subscribe();
// retryWhen - logique de retry personnaliséethis.http.get('/api/data').pipe( retryWhen(errors => errors.pipe( delay(1000), take(3) ) )).subscribe();Utility Operators
Section intitulée « Utility Operators »import { tap, delay, timeout, finalize } from 'rxjs/operators';
// tap - side effects (debugging, logging)this.http.get('/api/data').pipe( tap(data => console.log('Data:', data)), map(data => data.items)).subscribe();
// delay - delay emissionsof(1, 2, 3).pipe( delay(1000)).subscribe(x => console.log(x)); // Après 1 seconde
// timeout - error if no emission within timethis.http.get('/api/data').pipe( timeout(5000), // 5 seconds catchError(error => of([]))).subscribe();
// finalize - run code when observable completes/errorsthis.http.get('/api/data').pipe( finalize(() => this.loading = false)).subscribe();Common Patterns
Section intitulée « Common Patterns »Search with Debounce
Section intitulée « Search with Debounce »searchTerm$ = new Subject<string>();
ngOnInit() { this.searchTerm$.pipe( debounceTime(300), distinctUntilChanged(), switchMap(term => this.searchService.search(term)) ).subscribe(results => { this.results = results; });}
onSearch(term: string) { this.searchTerm$.next(term);}Unsubscribe Pattern
Section intitulée « Unsubscribe Pattern »private destroy$ = new Subject<void>();
ngOnInit() { this.dataService.getData().pipe( takeUntil(this.destroy$) ).subscribe(data => this.data = data);}
ngOnDestroy() { this.destroy$.next(); this.destroy$.complete();}Loading State
Section intitulée « Loading State »loadData() { this.loading = true;
this.http.get('/api/data').pipe( finalize(() => this.loading = false) ).subscribe( data => this.data = data, error => this.error = error );}private cache$ = new Map<string, Observable<any>>();
getData(id: string): Observable<any> { if (!this.cache$.has(id)) { this.cache$.set( id, this.http.get(`/api/data/${id}`).pipe(shareReplay(1)) ); } return this.cache$.get(id)!;}Bonnes Pratiques
Section intitulée « Bonnes Pratiques »- Utiliser
switchMappour les recherches (annuler le précédent) - Utiliser
mergeMappour les requêtes indépendantes - Utiliser
concatMappour les opérations séquentielles - Toujours gérer les erreurs avec
catchError - Utiliser
takeUntilpour se désabonner - Utiliser
shareReplaypour le caching - Utiliser
debounceTimepour les saisies utilisateur - Utiliser
distinctUntilChangedpour éviter les doublons - Éviter les subscriptions imbriquées (utiliser les opérateurs de flattening)

