import{of,interval}from'rxjs';import{switchMap,take}from'rxjs/operators';// Basic usageof('first','second').pipe(switchMap(val=>interval(1000).pipe(take(2)))).subscribe(console.log);// Cancels 'first', emits 0, 1 for 'second'// Advanced usage (search auto-complete)constsearchInput$=of('apple','app','apple pie');searchInput$.pipe(switchMap(query=>fakeApiSearch(query))// Cancel previous search if a new one occurs).subscribe(console.log);functionfakeApiSearch(query:string){console.log(`Searching for ${query}`);returnof(`Results for ${query}`);}
4. combineLatest
Basic: Combine latest values from multiple observables.
import{of}from'rxjs';import{debounceTime}from'rxjs/operators';// Basic usageof(1,2,3).pipe(debounceTime(1000)).subscribe(console.log);// Emits only after 1 second delay// Advanced usage (debouncing API calls)constuserInput$=of('search term');userInput$.pipe(debounceTime(300))// Delay API call until typing stops.subscribe(query=>performSearch(query));functionperformSearch(query:string){console.log(`Searching for: ${query}`);}
7. takeUntil
Basic: Take values until another observable emits.
Advanced: Auto-unsubscribe on component destruction.
import{of,throwError}from'rxjs';import{catchError,retry}from'rxjs/operators';// Basic usagethrowError('Error!').pipe(catchError(err=>of(`Caught: ${err}`))).subscribe(console.log);// Output: 'Caught: Error!'// Advanced usage (retry and then handle error)of('Request').pipe(mergeMap(_=>throwError('Network error')),// Simulate network errorretry(3),// Retry up to 3 timescatchError(err=>of(`Failed after retries: ${err}`))).subscribe(console.log);// Output after retries fail: 'Failed after retries: Network error'
9. concatMap
Basic: Map each value to an observable, preserving order.
import{of,interval}from'rxjs';import{exhaustMap,take}from'rxjs/operators';// Basic usageof('A','B').pipe(exhaustMap(val=>interval(1000).pipe(take(2)))).subscribe(console.log);// Ignores 'B' since 'A' is not complete// Advanced usage (button click prevention)constbuttonClick$=of('click');buttonClick$.pipe(exhaustMap(()=>fakeLongRequest())// Ignores further clicks until request completes).subscribe(console.log);functionfakeLongRequest(){returnof('Request complete').pipe(delay(2000));// Simulates long request}
11. tap
Basic: Perform side effects without altering emitted values.
import{of}from'rxjs';import{share,map}from'rxjs/operators';// Basic usageconstshared$=of('Shared data').pipe(share());shared$.subscribe(console.log);// Output: 'Shared data' (only called once)// Advanced usage (shared API response)constapiResponse$=of({id:1,name:'Alice'}).pipe(share());apiResponse$.subscribe(console.log);// First subscriberapiResponse$.subscribe(console.log);// Second subscriber, no new request
import{of,throwError,timer}from'rxjs';import{retryWhen,delay,mergeMap}from'rxjs/operators';// Basic usagethrowError('Error!').pipe(retryWhen(errors=>errors.pipe(delay(1000))// Retry after 1 second on error)).subscribe(console.log,console.error);// Advanced usage (exponential backoff)constsource$=throwError('Network error');source$.pipe(retryWhen(errors=>errors.pipe(mergeMap((error,i)=>{constretryAttempt=i+1;if(retryAttempt>3){returnthrowError(`Failed after ${retryAttempt} attempts`);}console.log(`Retrying in ${retryAttempt} second(s)...`);returntimer(retryAttempt*1000);// Exponential delay})))).subscribe(console.log,console.error);
16. zip
Basic: Combine values from multiple observables into tuples.
Advanced: Wait for paired data from different sources.
import{of,timer}from'rxjs';import{delayWhen}from'rxjs/operators';// Basic usageof('A','B','C').pipe(delayWhen(()=>timer(1000)))// Delays each by 1 second.subscribe(console.log);// Advanced usage (wait until user confirms before making an API call)constapiCall$=of('API call result');constuserConfirmed$=timer(3000);// Simulate 3-second delay for user confirmationapiCall$.pipe(delayWhen(()=>userConfirmed$)).subscribe(console.log);// Only emits after userConfirmed$ completes
20. partition
Basic: Split values into two groups based on a condition.
Advanced: Separate even and odd values or filter errors vs. success responses.
import{interval}from'rxjs';import{bufferTime}from'rxjs/operators';// Basic usageinterval(500).pipe(bufferTime(2000)).subscribe(console.log);// Output: [0,1,2,...] every 2 seconds// Advanced usage (batching user inputs)constuserInput$=interval(500).pipe(bufferTime(2000));userInput$.subscribe(batch=>{console.log(`Processing batch:`,batch);// Process inputs as a single batch});
23. windowCount
Basic: Emit windows of values based on count, outputting observables.
Advanced: Apply cumulative calculations to batches of values.
import{interval}from'rxjs';import{windowCount,mergeMap,reduce}from'rxjs/operators';// Basic usageinterval(500).pipe(windowCount(3),mergeMap(window$=>window$.pipe(reduce((acc,val)=>[...acc,val],[])))).subscribe(console.log);// Output: [0,1,2], [3,4,5], etc.// Advanced usage (calculate batch totals)interval(500).pipe(windowCount(5),mergeMap(window$=>window$.pipe(reduce((acc,value)=>acc+value,0))// Sum of each 5-value window)).subscribe(console.log);// Output: 10, 35, 60, etc. (sum of each window)
24. pairwise
Basic: Emit pairs of consecutive values.
Advanced: Detect value changes and apply transformation based on previous value.
import{fromEvent}from'rxjs';import{throttleTime}from'rxjs/operators';// Basic usageconstclicks$=fromEvent(document,'click');clicks$.pipe(throttleTime(1000)).subscribe(console.log);// Emits clicks every 1 second// Advanced usage (scroll events for infinite loading)constscroll$=fromEvent(window,'scroll');scroll$.pipe(throttleTime(500)).subscribe(()=>{// Load more content if scrolled near bottomif(window.innerHeight+window.scrollY>=document.body.offsetHeight){console.log('Load more content');}});
26. fromEvent
Usage: Creates an Observable that emits events of a specific type from an Angular component template element.
Angular has introduced several innovative features recently to improve reactivity, component lifecycle management, and lazy loading. Here’s a closer look at more of these features:
1. Signals (Angular 16+)
What it is: Signals are a reactivity model for managing component state, inspired by reactive programming concepts.
Use case: Provides a simpler way to manage local state in components, ideal for controlling reactivity without manual change detection.
import{signal,computed,effect}from'@angular/core';// Define a signalconstcounter=signal(0);// Computed signalconstdoubleCounter=computed(()=>counter()*2);// Effect on signaleffect(()=>{console.log(`Counter value: ${counter()}`);});// Update the signalcounter.set(counter()+1);// increments counter by 1
2. toSignal
What it is: Converts an observable to a signal for seamless integration with Angular’s signal-based reactivity model.
Use case: Ideal for integrating RxJS streams or service observables with components using signals.
import{interval}from'rxjs';import{toSignal}from'@angular/core/rxjs-interop';constinterval$=interval(1000);// emits every secondconstintervalSignal=toSignal(interval$);effect(()=>{console.log(`Interval signal value: ${intervalSignal()}`);});
3. defer Directive
What it is: A structural directive that defers rendering of components until specific conditions are met, like visibility or data readiness.
Use case: Ideal for improving performance by lazy-loading content.
import{DestroyRef}from'@angular/core';constructor(privatedestroyRef:DestroyRef){constmyResource=openResource();this.destroyRef.onDestroy(()=>{myResource.close();// Clean up when destroyed});}
5. Signal Store (Experimental)
What it is: Angular’s experimental state management solution with signals.
Use case: Provides a simple API for state management without needing traditional stores or observables.
Each of these operators and Angular features gives you powerful tools for managing state, reactivity, and performance. Replace any ... with additional details as needed.