RXJS

Top of Form

Bottom of Form

1. What is RxJS, and how is it used in Angular?


RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using Observables. It is extensively used in Angular for handling asynchronous data streams and events, such as HTTP requests, user interactions, or WebSocket messages. RxJS allows developers to work with asynchronous data using operators like map, filter, switchMap, mergeMap, etc. Angular leverages RxJS in components, services, and other parts of the application, especially for handling HTTP requests and reactive forms.


2. What are Observables in RxJS and how do they work in Angular?


An Observable is a core concept in RxJS. It represents a collection of future values or events. In Angular, an Observable is typically used to handle asynchronous operations like HTTP requests. Components subscribe to an Observable to get the values emitted by it. When an Observable emits a value, all subscribers are notified. Angular services return Observables for tasks like fetching data from APIs, and components subscribe to these Observables to display or use the data.

Example:

this.httpClient.get('/api/data').subscribe(data => {

  console.log(data);

});


3. What is the purpose of the async pipe in Angular?


The async pipe in Angular is used to automatically subscribe to an Observable or a Promise and return the latest emitted value. It also handles the unsubscription when the component is destroyed. This pipe is often used in templates to simplify working with Observables, eliminating the need to manually subscribe and unsubscribe.

Example:

<div *ngIf="data$ | async as data">

  {{ data.name }}

</div>


4. Explain the difference between switchMap and mergeMap in RxJS.

 

  • switchMap: This operator is used when you want to cancel the previous inner Observable whenever a new value is emitted. It switches to the latest Observable and unsubscribes from the previous one. It is particularly useful for scenarios like autocomplete or live search.
  • mergeMap: This operator is used when you want to merge multiple Observables into one without cancelling any previous ones. It subscribes to all inner Observables concurrently and emits all their values.

Example:

// Using switchMap

this.searchTerm$.pipe(

  switchMap(term => this.searchService.search(term))

);

 

// Using mergeMap

this.searchTerm$.pipe(

  mergeMap(term => this.searchService.search(term))

);


5. What is the difference between take(1) and first() operators in RxJS?

 

  • take(1): This operator allows you to take the first value emitted by the Observable and then automatically unsubscribe. It’s useful when you want to grab a single value without worrying about future emissions.
  • first(): Similar to take(1), but it also accepts a predicate to specify a condition for the first value emitted. If no predicate is provided, it behaves like take(1).

Example:

// take(1) example

this.httpClient.get('/api/data').pipe(take(1)).subscribe(data => console.log(data));

 

// first() with predicate

this.httpClient.get('/api/data').pipe(first(data => data.status === 'active')).subscribe(data => console.log(data));


6. How can you prevent memory leaks when working with RxJS in Angular?


Memory leaks in Angular can occur if Observables are not unsubscribed properly. Common strategies to avoid memory leaks:

  • Use the async pipe in templates, which handles unsubscription automatically.
  • Manually unsubscribe from Observables in the ngOnDestroy lifecycle hook.
  • Use operators like takeUntil to manage unsubscription based on another Observable (often a subject).

Example with takeUntil:

import { Subject } from 'rxjs';

 

export class MyComponent implements OnInit, OnDestroy {

  private destroy$ = new Subject<void>();

 

  ngOnInit() {

    this.myObservable$

      .pipe(takeUntil(this.destroy$))

      .subscribe(data => console.log(data));

  }

 

  ngOnDestroy() {

    this.destroy$.next();

    this.destroy$.complete();

  }

}


7. What does the debounceTime operator do in RxJS, and when should it be used?


The debounceTime operator is used to wait for a specified time period after the last emitted value before emitting the most recent one. It is commonly used to handle scenarios like user typing in a search input, where you want to wait for the user to stop typing before making an API call. It helps reduce the number of unnecessary API calls.

Example:

this.searchTerm$

  .pipe(debounceTime(300), switchMap(term => this.searchService.search(term)))

  .subscribe(results => console.log(results));


8. How do you handle errors in RxJS Observables in Angular?


You can handle errors in RxJS Observables using the catchError operator or the subscribe error callback. The catchError operator allows you to catch errors and handle them gracefully, such as by returning a fallback value or retrying the request.

Example using catchError:

this.httpClient.get('/api/data').pipe(

  catchError(error => {

    console.error('Error occurred:', error);

    return of([]); // Return fallback value

  })

).subscribe(data => console.log(data));


9. What is the ReplaySubject in RxJS, and how is it used?


A ReplaySubject is a type of Subject that remembers the previous emitted values and replays them to new subscribers. It can be useful when you want new subscribers to receive the most recent value or a set of recent values. You can specify how many values the ReplaySubject should replay by providing a buffer size.

Example:

const replaySubject = new ReplaySubject(2); // Replay last 2 values

replaySubject.next(1);

replaySubject.next(2);

replaySubject.next(3);

 

replaySubject.subscribe(value => console.log(value)); // Will receive 2 and 3


10. Explain the concept of "cold" and "hot" Observables.

 

  • Cold Observables: These are Observables that do not begin emitting values until they are subscribed to. Each subscription will get its own independent execution of the Observable.
  • Hot Observables: These are Observables that emit values regardless of subscriptions. Multiple subscribers will share the same execution of the Observable and receive the same emitted values.

Example:

  • HTTP requests are typically cold Observables, meaning each subscriber triggers a separate HTTP request.
  • A Subject is a hot Observable, as it will emit values to all subscribers immediately when they subscribe.

11. What is concatMap in RxJS and when would you use it?


The concatMap operator is used to map each emitted value to an inner Observable and concatenate the emissions from those inner Observables in a sequential order. Unlike mergeMap, concatMap ensures that each inner Observable completes before moving to the next one, so the order of emissions is preserved.

Use case: You would use concatMap when the order of the emissions matters and you need to wait for one task to complete before starting the next. For example, submitting form data sequentially.

Example:

this.formData$

  .pipe(concatMap(data => this.submitForm(data)))

  .subscribe(response => console.log(response));


12. What is the purpose of the shareReplay operator in RxJS?


The shareReplay operator is used to multicast an Observable to multiple subscribers, and it also replays a specified number of values to new subscribers. This is useful when you want to share an Observable among multiple consumers and avoid re-executing the underlying operation, such as a network request, for every new subscriber.

Use case: Avoiding duplicate HTTP requests when multiple components subscribe to the same Observable.

Example:

const sharedData$ = this.httpClient.get('/api/data').pipe(shareReplay(1));

sharedData$.subscribe(data => console.log('Subscriber 1:', data));

sharedData$.subscribe(data => console.log('Subscriber 2:', data));


13. What is switchMap and how does it differ from mergeMap?

 

  • switchMap: When a new value is emitted from the source Observable, switchMap cancels the previous inner Observable and switches to the new one. This is useful for scenarios where you need to cancel ongoing operations (e.g., switching between search terms in an input box).
  • mergeMap: Unlike switchMap, mergeMap does not cancel the previous inner Observable. It will merge the emissions from all inner Observables, allowing them to execute concurrently. This is useful when you need to handle multiple concurrent tasks and collect results from all of them.

Example of switchMap:

this.searchTerm$.pipe(

  switchMap(term => this.searchService.search(term))

).subscribe(results => console.log(results));

Example of mergeMap:

this.searchTerm$.pipe(

  mergeMap(term => this.searchService.search(term))

).subscribe(results => console.log(results));


14. What does takeUntil do, and how can it be useful in Angular?


The takeUntil operator is used to automatically unsubscribe from an Observable when another Observable emits a value. This is particularly useful for managing subscriptions in Angular components, ensuring they are properly cleaned up when a component is destroyed or when certain conditions are met.

Use case: Preventing memory leaks by ensuring subscriptions are unsubscribed when the component is destroyed.

Example:

import { Subject } from 'rxjs';

 

export class MyComponent implements OnInit, OnDestroy {

  private destroy$ = new Subject<void>();

 

  ngOnInit() {

    this.httpClient.get('/api/data').pipe(

      takeUntil(this.destroy$)

    ).subscribe(data => console.log(data));

  }

 

  ngOnDestroy() {

    this.destroy$.next();

    this.destroy$.complete();

  }

}


15. What is the difference between tap and map in RxJS?

 

  • tap: The tap operator is used for side effects. It does not alter the data passing through it. It allows you to perform actions like logging, debugging, or calling functions, but it does not change the emitted values.
  • map: The map operator transforms the emitted values. It takes the input value, processes it, and outputs a new value. The primary purpose of map is to modify the data flow, not just to perform side effects.

Example:

// Using `map` to transform data

this.httpClient.get('/api/data').pipe(

  map(data => data.items)

).subscribe(items => console.log(items));

 

// Using `tap` to log data without modifying it

this.httpClient.get('/api/data').pipe(

  tap(data => console.log('Received data:', data))

).subscribe();


16. What is the purpose of the auditTime operator in RxJS?


The auditTime operator is used to emit the latest value from the source Observable only after a specified amount of time has passed. It will ignore any values emitted during that time window and will only emit the most recent value once the time period is over.

Use case: This is useful for scenarios like limiting the frequency of user input handling, such as implementing efficient scroll or resize event listeners.

Example:

this.scrollEvent$.pipe(

  auditTime(300)

).subscribe(() => {

  console.log('Scrolled after 300ms');

});


17. What is the debounce operator in RxJS, and how does it differ from debounceTime?


The debounce operator is similar to debounceTime, but it works based on the value of the emitted item rather than a fixed time. It allows you to wait for the source Observable to stop emitting values for a specific amount of time before emitting the most recent one. This is often used when you need to debounce user input, like a search bar, but with a condition based on the emitted value.

Use case: Debouncing user inputs that require specific conditions, like waiting for a value change to meet a certain criterion.

Example:

this.searchTerm$.pipe(

  debounce(() => this.myCustomDebounceCondition())

).subscribe(result => {

  console.log(result);

});


18. How can you use combineLatest in Angular?


The combineLatest operator combines the latest values from multiple Observables and emits the latest value from each source Observable as an array or object when any of the Observables emits a new value.

Use case: Useful when you need to combine data from multiple Observables (e.g., form fields, user profile data, etc.).

Example:

import { combineLatest } from 'rxjs';

 

combineLatest([this.username$, this.password$]).subscribe(([username, password]) => {

  console.log('Username:', username);

  console.log('Password:', password);

});


19. What is the interval function in RxJS, and how can you use it in Angular?


The interval function creates an Observable that emits increasing integer values at regular intervals (in milliseconds). This can be useful for periodic tasks or polling.

Use case: Polling a server or running an animation at a fixed interval.

Example:

import { interval } from 'rxjs';

 

const timer$ = interval(1000); // Emits every second

 

timer$.subscribe(val => {

  console.log('Tick:', val);

});


20. How would you implement retry logic with RxJS in Angular?


You can use the retry or retryWhen operators in RxJS to automatically retry a failed Observable operation. retry allows you to specify a number of retries, while retryWhen gives you more control over the retry logic, including delays between retries.

Use case: Retrying an HTTP request when it fails temporarily.

Example with retry:

this.httpClient.get('/api/data').pipe(

  retry(3)  // Retry up to 3 times

).subscribe(data => console.log(data), error => console.error(error));

Example with retryWhen (using delay):

import { of } from 'rxjs';

import { retryWhen, delay, take } from 'rxjs/operators';

 

this.httpClient.get('/api/data').pipe(

  retryWhen(errors => errors.pipe(

    delay(1000),  // Wait 1 second between retries

    take(3)       // Retry up to 3 times

  ))

).subscribe(data => console.log(data), error => console.error(error));


21. What is share in RxJS, and how does it work in Angular?


The share operator is used to share a single subscription to an Observable among multiple subscribers. It works by multicast the source Observable, so that it does not execute multiple times (like making multiple HTTP requests). It’s a combination of publish and refCount that automatically subscribes and unsubscribes based on the number of active subscribers.

Use case: Avoiding redundant HTTP requests or expensive operations when multiple components need the same data.

Example:

const sharedData$ = this.httpClient.get('/api/data').pipe(share());

 

sharedData$.subscribe(data => console.log('Subscriber 1:', data));

sharedData$.subscribe(data => console.log('Subscriber 2:', data));


22. What is concatAll in RxJS and when should you use it?


The concatAll operator is used to flatten an Observable of Observables by subscribing to each inner Observable sequentially. It ensures that the outer Observable will emit values from one inner Observable at a time, and only move to the next inner Observable after the current one completes.

Use case: Useful when you need to execute asynchronous tasks in sequence, where one task must complete before the next starts.

Example:

this.outerObservable.pipe(concatAll()).subscribe(result => {

  console.log(result); // The inner Observables will be processed one at a time.

});


23. What is exhaustMap in RxJS, and when is it useful?


The exhaustMap operator is used to map to an inner Observable but ignores all incoming emissions from the source Observable until the current inner Observable completes. This ensures that only one inner Observable is active at any time and ignores any new emissions during that time.

Use case: Useful in scenarios where you don't want to start a new operation while an ongoing one is still running, such as form submission where you don’t want to trigger multiple requests in parallel.

Example:

this.submitForm$

  .pipe(exhaustMap(formData => this.formService.submit(formData)))

  .subscribe(response => console.log(response));


24. What is takeWhile in RxJS and how does it work?


The takeWhile operator allows you to emit values from an Observable until a specified condition is no longer true. Once the condition becomes false, it completes the Observable. Unlike take, which limits the number of values, takeWhile is based on a condition.

Use case: Stop processing values once a certain condition is met, for example, when you reach the end of a list or stop a timer.

Example:

this.timer$.pipe(takeWhile(val => val < 10)).subscribe(val => {

  console.log(val); // Stops emitting values once `val` is greater than or equal to 10.

});


25. How does window operator work in RxJS?


The window operator is used to group emitted values from the source Observable into windows (Observables), which are emitted as separate Observables. These windows can be controlled using another Observable, and each window emits values until it is closed, then a new window is started.

Use case: It’s helpful when you want to break the stream of values into smaller chunks, such as when handling events in batches.

Example:

import { interval } from 'rxjs';

import { window, take, mergeAll } from 'rxjs/operators';

 

interval(1000).pipe(

  window(interval(3000)), // Group values emitted every 3 seconds

  take(2), // Take two windows

  mergeAll() // Merge the windowed Observables into one

).subscribe(value => console.log(value));


26. What is merge in RxJS and how is it different from concat?

 

  • merge: Combines multiple Observables into a single Observable, emitting values from all Observables concurrently, without waiting for each Observable to complete first. This means that multiple inner Observables may emit values simultaneously.
  • concat: Combines multiple Observables, but ensures that each Observable completes before the next one is subscribed to. This ensures that the order of emissions is strictly maintained.

Use case:

  • Use merge when you want to handle concurrent requests or parallel streams.
  • Use concat when you need to process tasks sequentially.

Example using merge:

import { merge } from 'rxjs';

 

merge(observable1, observable2).subscribe(data => console.log(data));

Example using concat:

import { concat } from 'rxjs';

 

concat(observable1, observable2).subscribe(data => console.log(data));


27. What does distinctUntilChanged do in RxJS?


The distinctUntilChanged operator ensures that only distinct values are emitted based on consecutive emissions from the source Observable. It compares the current value to the previous value, and only emits the new value if it is different.

Use case: It is used to filter out consecutive duplicate values, such as when observing a value that only changes when there’s a meaningful change (e.g., form data input or button click).

Example:

this.inputValue$.pipe(

  distinctUntilChanged()

).subscribe(value => console.log(value)); // Emits only when the value is different from the previous one


28. What is the delay operator in RxJS and when is it useful?


The delay operator is used to delay the emissions of an Observable by a specified amount of time. It’s useful when you want to simulate a delay or pause before emitting values.

Use case: You can use delay to simulate network latency in tests, or to create UI delays like showing loading indicators.

Example:

this.httpClient.get('/api/data').pipe(

  delay(2000)  // Delay the emission by 2 seconds

).subscribe(data => console.log(data));


29. How does zip operator work in RxJS?


The zip operator combines multiple Observables into a single Observable by emitting a combined value when each of the source Observables emits a value. The combined value is emitted as an array (or tuple) of corresponding values from each of the source Observables, and it only emits when all Observables have emitted a value.

Use case: Used when you need to combine data from multiple sources, but you want to process the values only when each Observable has emitted an item.

Example:

import { zip } from 'rxjs';

 

const observable1 = of(1, 2, 3);

const observable2 = of('A', 'B', 'C');

 

zip(observable1, observable2).subscribe(([num, char]) => {

  console.log(num, char); // Output will be: 1 A, 2 B, 3 C

});


30. What is the finalize operator in RxJS and how is it used in Angular?


The finalize operator allows you to perform a side-effect action (like cleanup) when an Observable completes or errors out. It’s useful when you need to trigger actions such as stopping a loading indicator or cleaning up resources, regardless of whether the Observable succeeds or fails.

Use case: It is often used to hide a loading spinner or dismiss any ongoing UI actions once the Observable completes.

Example:

this.httpClient.get('/api/data').pipe(

  finalize(() => {

    this.isLoading = false; // Hide loading spinner

  })

).subscribe(data => {

  console.log(data);

});


31. What is buffer in RxJS, and when would you use it?


The buffer operator collects values from the source Observable into an array until another Observable emits a value. Once the other Observable emits, the accumulated values are emitted as an array, and the collection process starts over.

Use case: Useful when you need to group emissions into arrays (or "batches") based on some external trigger, such as collecting events until a user stops typing or some timeout.

Example:

import { buffer, interval, take } from 'rxjs';

 

interval(1000).pipe(

  take(5), // Emit 5 values from the source Observable

  buffer(interval(3000)) // Collect values until the next 3-second interval

).subscribe(values => {

  console.log('Buffered Values:', values); // Emit buffered values every 3 seconds

});


32. What does startWith do in RxJS?


The startWith operator is used to emit a specified value before any other emissions from the source Observable. This allows you to provide an initial value when subscribing to the Observable.

Use case: Use startWith to initialize a value, such as displaying a default value before an API call completes or before any user interaction.

Example:

this.data$.pipe(

  startWith('Loading...')

).subscribe(value => console.log(value)); // Emits 'Loading...' before the actual data


33. What is catchError in RxJS, and how can it be used in Angular?


The catchError operator is used to handle errors that occur in an Observable. It allows you to catch errors and either return a fallback Observable or rethrow the error to be handled downstream.

Use case: Use catchError when dealing with HTTP requests or any other Observables where errors need to be handled gracefully, such as showing an error message or retrying the operation.

Example:

import { catchError } from 'rxjs/operators';

 

this.httpClient.get('/api/data').pipe(

  catchError(error => {

    console.error('Error occurred:', error);

    return of([]); // Return a fallback value (empty array)

  })

).subscribe(data => console.log(data));


34. What is pairwise in RxJS?


The pairwise operator emits the previous and current values from the source Observable as an array. It is useful when you need to track the change between consecutive emissions.

Use case: Track the difference or changes between consecutive values, like comparing a previous and current value for state changes.

Example:

import { pairwise } from 'rxjs';

 

this.value$.pipe(

  pairwise() // Emits the previous and current values as a tuple

).subscribe(([prev, current]) => {

  console.log('Previous:', prev, 'Current:', current);

});


35. What is fromEvent in RxJS, and how is it used in Angular?


The fromEvent operator is used to create an Observable from DOM events. It is useful for event handling, such as listening for user interactions like clicks, mouse movements, or key presses.

Use case: Handle events in Angular components by subscribing to DOM events using RxJS.

Example:

import { fromEvent } from 'rxjs';

 

ngOnInit() {

  const click$ = fromEvent(document, 'click');

  click$.subscribe(event => {

    console.log('Document clicked:', event);

  });

}


36. What is the mergeMap operator and how is it different from switchMap?

 

  • mergeMap: Maps a source value to an inner Observable and merges all the emissions from these inner Observables. All inner Observables are subscribed to concurrently, meaning they are handled in parallel.
  • switchMap: Similar to mergeMap, but with a key difference. It cancels the previous inner Observable whenever a new value is emitted by the source Observable. This ensures that only the latest inner Observable is active, making it suitable for cases like search or user input.

Use case:

  • Use mergeMap for handling concurrent requests.
  • Use switchMap for cases where only the latest operation matters, like live search.

Example using mergeMap:

this.searchTerm$.pipe(

  mergeMap(term => this.searchService.search(term))

).subscribe(results => console.log(results));

Example using switchMap:

this.searchTerm$.pipe(

  switchMap(term => this.searchService.search(term))

).subscribe(results => console.log(results));


37. How can you create an Observable from a Promise in RxJS?


You can use the from operator to convert a Promise into an Observable. Once the Promise resolves, the Observable emits the resolved value.

Use case: Use from when you need to integrate Promise-based APIs with RxJS Observables.

Example:

import { from } from 'rxjs';

 

const promise = new Promise(resolve => resolve('Data from Promise'));

 

from(promise).subscribe(data => {

  console.log(data); // Outputs: 'Data from Promise'

});


38. What is asyncScheduler in RxJS?


The asyncScheduler is one of the schedulers provided by RxJS and it allows you to schedule tasks asynchronously in the future, based on the event loop. It’s often used in combination with operators like observeOn or schedule.

Use case: Use asyncScheduler to schedule tasks or handle deferred operations without blocking the main thread.

Example:

import { asyncScheduler } from 'rxjs';

import { observeOn } from 'rxjs/operators';

 

this.observable$.pipe(

  observeOn(asyncScheduler)

).subscribe(value => {

  console.log(value); // The values will be emitted asynchronously

});


39. What is the difference between forkJoin and zip in RxJS?

 

  • forkJoin: Combines multiple Observables and waits for all of them to complete before emitting an array of their last emitted values. It is only triggered once all the source Observables complete.
  • zip: Combines multiple Observables and emits the values as arrays of corresponding emissions from each Observable. It emits only when each Observable has emitted a value at the same time.

Use case:

  • Use forkJoin when you need the results of multiple Observables once they are all completed (e.g., when fetching data from multiple endpoints).
  • Use zip when you want to combine values from multiple streams, but you want them emitted together based on their order.

Example using forkJoin:

import { forkJoin } from 'rxjs';

 

forkJoin({

  data1: this.httpClient.get('/api/data1'),

  data2: this.httpClient.get('/api/data2')

}).subscribe(result => {

  console.log(result); // { data1: value1, data2: value2 }

});

Example using zip:

import { zip } from 'rxjs';

 

zip(this.httpClient.get('/api/data1'), this.httpClient.get('/api/data2')).subscribe(([data1, data2]) => {

  console.log(data1, data2); // Emits as pairs of corresponding values

});


40. What is retryWhen and how does it differ from retry?

 

  • retry: Retries a failed Observable a specified number of times. After the retries, the Observable completes or errors out.
  • retryWhen: Allows for more complex retry logic. It takes a function that can return an Observable to determine when the retry will happen. You can introduce delays, conditions, and custom logic for retries.

Use case: Use retryWhen for advanced retry strategies such as exponential backoff or delayed retries.

Example using retry:

this.httpClient.get('/api/data').pipe(

  retry(3) // Retry up to 3 times

).subscribe();

Example using retryWhen:

import { of } from 'rxjs';

import { retryWhen, delay, take } from 'rxjs/operators';

 

this.httpClient.get('/api/data').pipe(

  retryWhen(errors => errors.pipe(

    delay(1000),  // Delay before retrying

    take(3)       // Retry 3 times

  ))

).subscribe();


41. What is concatMap in RxJS, and how does it differ from mergeMap?

 

  • concatMap: Maps a source value to an inner Observable and subscribes to each inner Observable sequentially. It waits for one inner Observable to complete before subscribing to the next.
  • mergeMap: Maps a source value to an inner Observable and subscribes to all inner Observables concurrently. This means the emissions from inner Observables may be interleaved.

Use case:

  • Use concatMap when you need to ensure that the operations happen sequentially, such as when the order of execution matters (e.g., step-by-step processing).
  • Use mergeMap when you want to handle multiple operations concurrently.

Example using concatMap:

this.data$.pipe(

  concatMap(item => this.processItemSequentially(item))

).subscribe(result => console.log(result));

Example using mergeMap:

this.data$.pipe(

  mergeMap(item => this.processItemConcurrently(item))

).subscribe(result => console.log(result));


42. What is the difference between observeOn and subscribeOn in RxJS?

 

  • observeOn: Specifies the scheduler on which the Observable will operate when emitting values. It controls on which scheduler the Observables' emissions happen.
  • subscribeOn: Specifies the scheduler on which the subscription to the Observable should occur. It controls on which scheduler the subscription and initialization logic for the Observable happens.

Use case:

  • Use observeOn to determine when and where values emitted by an Observable will be observed.
  • Use subscribeOn to control when the subscription to the Observable will be executed.

Example using observeOn:

import { observeOn, asyncScheduler } from 'rxjs';

 

this.observable$.pipe(

  observeOn(asyncScheduler)

).subscribe(value => console.log(value)); // Emission happens asynchronously

Example using subscribeOn:

import { subscribeOn, asyncScheduler } from 'rxjs';

 

this.observable$.pipe(

  subscribeOn(asyncScheduler)

).subscribe(value => console.log(value)); // Subscription starts asynchronously


43. What is withLatestFrom in RxJS?


The withLatestFrom operator combines the latest value from another Observable with each value emitted by the source Observable. It doesn't subscribe to the second Observable, but instead waits for the latest emitted value when the source Observable emits a value.

Use case: It's useful when you need to combine a value from the source Observable with the most recent value from another Observable (e.g., combining user input with the latest state).

Example:

import { withLatestFrom } from 'rxjs';

 

this.source$.pipe(

  withLatestFrom(this.latestValue$)

).subscribe(([sourceValue, latestValue]) => {

  console.log('Source:', sourceValue, 'Latest:', latestValue);

});


44. What is the debounceTime operator and when would you use it in Angular?


The debounceTime operator delays the emissions of an Observable for a specified amount of time after the most recent emission. It helps in reducing the frequency of emissions when you expect rapid, repeated inputs, such as keypresses.

Use case: Commonly used for scenarios like search input or autocomplete, where you want to wait for the user to finish typing before making an HTTP request.

Example:

import { debounceTime } from 'rxjs';

 

this.searchInput$.pipe(

  debounceTime(300) // Wait for 300ms of inactivity before emitting the value

).subscribe(searchTerm => {

  this.search(searchTerm); // Perform search after debounce

});


45. What is tap in RxJS, and when would you use it?


The tap operator allows you to perform side-effects without modifying the values emitted by the Observable. It's often used for logging, debugging, or triggering actions that don't affect the flow of the Observable chain.

Use case: Use tap for side-effects like logging, setting flags, or updating variables.

Example:

import { tap } from 'rxjs';

 

this.data$.pipe(

  tap(data => console.log('Received data:', data)) // Logging the data without changing it

).subscribe();


46. What does finalize do in RxJS?


The finalize operator is used to execute a side-effect action when the Observable completes or errors out. It ensures that clean-up actions are triggered regardless of whether the Observable completes successfully or encounters an error.

Use case: Commonly used for cleanup tasks, like hiding loading spinners, after the Observable completes or errors.

Example:

import { finalize } from 'rxjs';

 

this.httpClient.get('/api/data').pipe(

  finalize(() => {

    this.loading = false; // Hide the loading spinner

  })

).subscribe();


47. How does shareReplay work in RxJS?


The shareReplay operator is used to share the emissions of an Observable among multiple subscribers. It also replays the last emitted value to new subscribers, ensuring that they receive the most recent emission when they subscribe.

Use case: This is useful in scenarios where you have multiple consumers for the same data (e.g., caching results) and you want to avoid re-executing the Observable for each subscriber.

Example:

import { shareReplay } from 'rxjs';

 

const shared$ = this.httpClient.get('/api/data').pipe(

  shareReplay(1) // Replay the last emitted value to new subscribers

);

 

shared$.subscribe(data => console.log('Subscriber 1:', data));

shared$.subscribe(data => console.log('Subscriber 2:', data)); // Receives the cached data from the first emission


48. What is auditTime in RxJS?


The auditTime operator limits the frequency of emissions from an Observable. It allows the source Observable to emit values within a specified window, but only emits the most recent value at the end of each time window.

Use case: It's useful when you need to rate-limit or throttle user interactions, like limiting the number of API calls during rapid events.

Example:

import { auditTime } from 'rxjs';

 

this.input$.pipe(

  auditTime(1000) // Emit only the most recent value every 1000ms

).subscribe(value => {

  console.log(value); // User input will be processed only once every second

});


49. What is merge in RxJS and when would you use it?


The merge operator combines multiple Observables into a single Observable and emits values from all the Observables concurrently. It does not wait for any Observable to complete before emitting the next value.

Use case: Use merge when you need to subscribe to multiple Observables concurrently, for example when handling multiple user actions or API requests in parallel.

Example:

import { merge } from 'rxjs';

 

const observable1 = this.dataService.getData1();

const observable2 = this.dataService.getData2();

 

merge(observable1, observable2).subscribe(result => {

  console.log('Result:', result);

});


50. What is takeUntil in RxJS?


The takeUntil operator emits values from the source Observable until a notifier Observable emits a value. This is useful for unsubscribing from an Observable based on some external condition or event.

Use case: Often used for unsubscribing from an Observable when a component is destroyed or a specific event occurs.

Example:

import { takeUntil } from 'rxjs';

 

const notifier$ = this.destroy$.pipe();

 

this.data$.pipe(

  takeUntil(notifier$) // Will complete the Observable when notifier$ emits

).subscribe();


51. What is the bufferTime operator in RxJS?


The bufferTime operator collects values emitted by an Observable into an array within a specified time window and emits those values as an array. After the time window ends, it emits the buffered values and starts collecting new values for the next window.

Use case: Useful when you want to batch emissions over a time window, such as collecting events over a short period and processing them in bulk.

Example:

import { bufferTime } from 'rxjs';

 

this.click$.pipe(

  bufferTime(3000) // Collect clicks for 3 seconds

).subscribe(clicks => {

  console.log('Buffered clicks:', clicks);

});


52. What is switchAll in RxJS, and when would you use it?


The switchAll operator is used to switch from the current inner Observable to a new inner Observable. When a new inner Observable is emitted, the current one is unsubscribed from, and the new Observable starts emitting values.

Use case: Use switchAll when you need to cancel the previous inner Observable and only keep the latest one active. This is useful for scenarios like live search or switching between different asynchronous operations.

Example:

import { switchAll } from 'rxjs';

 

this.searchQuery$.pipe(

  switchAll() // Switch to the latest Observable when a new search query is emitted

).subscribe(results => {

  console.log('Search results:', results);

});


53. What is exhaustMap in RxJS, and how does it differ from switchMap?

 

  • exhaustMap: Maps a value from the source Observable to an inner Observable, but ignores new emissions from the source Observable while the current inner Observable is still running. This means it will only switch to a new inner Observable once the current one has completed.
  • switchMap: Switches to a new inner Observable every time the source Observable emits a new value, canceling the previous one.

Use case:

  • Use exhaustMap when you don't want to handle multiple concurrent requests (e.g., submitting a form only once until the previous submission is complete).
  • Use switchMap when you only care about the latest emission, and cancel previous emissions.

Example using exhaustMap:

import { exhaustMap } from 'rxjs';

 

this.formSubmit$.pipe(

  exhaustMap(() => this.submitForm())

).subscribe(result => {

  console.log('Form submitted successfully:', result);

});

Example using switchMap:

import { switchMap } from 'rxjs';

 

this.formSubmit$.pipe(

  switchMap(() => this.submitForm())

).subscribe(result => {

  console.log('Form submitted with latest data:', result);

});


54. What is repeatWhen in RxJS?


The repeatWhen operator allows you to repeat an Observable based on the emissions of another Observable. It gives you control over when the source Observable should repeat by using the notifier Observable.

Use case: Use repeatWhen when you need to trigger the repetition of an Observable based on custom logic, such as retrying an operation or looping until a condition is met.

Example:

import { repeatWhen, delay } from 'rxjs';

 

this.httpClient.get('/api/data').pipe(

  repeatWhen(notifications => notifications.pipe(

    delay(2000) // Repeat the request every 2 seconds

  ))

).subscribe(data => {

  console.log('Fetched data:', data);

});


55. What is the difference between concat and concatMap in RxJS?

 

  • concat: Combines multiple Observables into a single Observable and emits their values sequentially, waiting for each Observable to complete before moving on to the next one.
  • concatMap: Maps each value from the source Observable to an inner Observable and subscribes to each inner Observable one by one, ensuring sequential emission.

Use case:

  • Use concat to concatenate multiple Observables together and ensure their emissions happen in sequence.
  • Use concatMap when you need to map each source emission to an inner Observable and ensure their sequential execution.

Example using concat:

import { concat } from 'rxjs';

 

const observable1 = this.httpClient.get('/api/first');

const observable2 = this.httpClient.get('/api/second');

 

concat(observable1, observable2).subscribe(data => {

  console.log('Received data:', data);

});

Example using concatMap:

import { concatMap } from 'rxjs';

 

this.data$.pipe(

  concatMap(item => this.fetchData(item))

).subscribe(data => {

  console.log('Fetched data:', data);

});


56. What is share in RxJS, and when would you use it?


The share operator is a shorthand for combining the behavior of multicast and refCount to share the source Observable. It allows multiple subscribers to share the same Observable execution, preventing the source Observable from being executed multiple times.

Use case: Use share when you want to share a single subscription to an Observable across multiple subscribers, like caching the result of an HTTP request and preventing multiple network calls.

Example:

import { share } from 'rxjs';

 

const shared$ = this.httpClient.get('/api/data').pipe(

  share()

);

 

shared$.subscribe(data => console.log('Subscriber 1:', data));

shared$.subscribe(data => console.log('Subscriber 2:', data)); // Shared subscription


57. What is delayWhen in RxJS?


The delayWhen operator delays the emission of values from the source Observable based on the emission of another Observable. You can specify how long to delay using a notifier Observable.

Use case: Use delayWhen when you want to delay values based on a dynamic condition (e.g., waiting for some external event or timer).

Example:

import { delayWhen, timer } from 'rxjs';

 

this.source$.pipe(

  delayWhen(() => timer(1000)) // Delay by 1 second for each emission

).subscribe(value => {

  console.log('Delayed value:', value);

});


58. What is debounce vs debounceTime in RxJS?

 

  • debounceTime: Delays the emission of values for a specified amount of time after the most recent emission, ensuring that only the final value in a burst of emissions is emitted after the specified time.
  • debounce: Similar to debounceTime, but instead of using a fixed time, it allows you to specify a custom logic to return an Observable that defines how long to wait before emitting the value.

Use case:

  • Use debounceTime for simple, time-based debounce scenarios (e.g., for search inputs).
  • Use debounce for more complex or dynamic debounce behavior where the delay might depend on the emitted values.

Example using debounceTime:

import { debounceTime } from 'rxjs';

 

this.search$.pipe(

  debounceTime(300) // Wait for 300ms of inactivity

).subscribe(query => {

  console.log('Search query:', query);

});

Example using debounce:

import { debounce } from 'rxjs';

 

this.search$.pipe(

  debounce(() => this.api.getDelay()) // Delay based on the response from another API call

).subscribe(query => {

  console.log('Search query:', query);

});


59. What is race in RxJS?


The race operator takes multiple Observables as input and emits values from the first Observable that emits a value. If one of the Observables emits a value first, the rest are ignored.

Use case: Use race when you need to select the fastest Observable from multiple sources, like fetching data from multiple APIs and using the first response.

Example:

import { race, of, timer } from 'rxjs';

 

const fastest$ = race(

  timer(1000, 2000),

  timer(500, 1000)

);

 

fastest$.subscribe(value => {

  console.log('The fastest Observable emitted:', value);

});


60. How does bufferCount work in RxJS?


The bufferCount operator collects values into an array and emits the array once the specified number of values have been emitted. After each emission, a new buffer is started.

Use case: Use bufferCount when you need to group emissions into fixed-size chunks, for example, batching API requests in groups of a specific size.

Example:

import { bufferCount } from 'rxjs';

 

this.data$.pipe(

  bufferCount(3) // Emit every 3 values as an array

).subscribe(values => {

  console.log('Buffered values:', values);

});


61. What is combineLatest in RxJS and when would you use it?


The combineLatest operator combines the latest values from multiple Observables. It waits for each Observable to emit at least one value, and then emits the latest values from each of the provided Observables every time any of them emits.

Use case: Use combineLatest when you need to combine values from multiple sources and react to any change in the latest emissions. It’s useful for scenarios like combining form input values, user preferences, or state updates.

Example:

import { combineLatest } from 'rxjs';

 

combineLatest([this.observable1$, this.observable2$]).subscribe(([value1, value2]) => {

  console.log('Latest values:', value1, value2);

});


62. What is startWith in RxJS?


The startWith operator emits a specified value before any values from the source Observable are emitted. This is useful when you want to initialize a stream with a default value.

Use case: Use startWith when you need to emit a default value or trigger a state update immediately when an Observable is subscribed to.

Example:

import { startWith } from 'rxjs';

 

this.data$.pipe(

  startWith('Initial value') // Emit 'Initial value' first before any other emissions

).subscribe(value => {

  console.log('Emitted:', value);

});


63. What is groupBy in RxJS and when should you use it?


The groupBy operator groups the emitted values from the source Observable into multiple inner Observables based on a key. Each group emits values associated with the group’s key, which can be processed independently.

Use case: Use groupBy when you need to process grouped data, such as categorizing user activities, items in a shopping cart, or events based on some attribute (e.g., grouping items by category).

Example:

import { groupBy, mergeMap } from 'rxjs';

 

this.items$.pipe(

  groupBy(item => item.category),

  mergeMap(group$ => group$.pipe(

    // Process each group (category) separately

    map(group => ({ category: group.key, items: group }))

  ))

).subscribe(result => {

  console.log(result); // Processed categories and their items

});


64. What is takeWhile in RxJS and how does it differ from takeUntil?

 

  • takeWhile: Emits values from the source Observable until a provided condition returns false. It stops emitting values as soon as the condition becomes false, but it can emit values while the condition is true.
  • takeUntil: Emits values from the source Observable until another Observable emits a value (usually a notifier), at which point it stops.

Use case:

  • Use takeWhile when you want to stop emitting values based on a condition.
  • Use takeUntil when you want to stop emitting values when a specific notifier Observable emits.

Example using takeWhile:

import { takeWhile } from 'rxjs';

 

this.data$.pipe(

  takeWhile(item => item < 10) // Stop emitting if item is >= 10

).subscribe(value => {

  console.log(value);

});

Example using takeUntil:

import { takeUntil } from 'rxjs';

 

this.data$.pipe(

  takeUntil(this.stop$) // Stop emitting when `stop$` emits

).subscribe(value => {

  console.log(value);

});


65. What is mergeScan in RxJS?


The mergeScan operator is similar to scan, but it allows for concurrent execution of the inner Observables. It accumulates a state based on the emissions of an inner Observable while merging multiple inner Observables. Unlike concatMap, which executes inner Observables sequentially, mergeScan allows for concurrent inner emissions.

Use case: Use mergeScan when you want to maintain a running state based on emissions from multiple concurrent inner Observables, such as accumulating results from multiple network requests.

Example:

import { mergeScan } from 'rxjs';

 

this.data$.pipe(

  mergeScan((acc, item) => this.fetchData(item).pipe(map(res => acc + res)), 0) // Accumulate results

).subscribe(result => {

  console.log('Accumulated result:', result);

});


66. What is retryWhen in RxJS and how does it differ from retry?

 

  • retry: Automatically retries the source Observable a specified number of times if it fails (e.g., due to an error), without any conditions or delay.
  • retryWhen: Allows you to specify a custom retry strategy by providing a function that returns an Observable. This Observable can emit values that determine when to retry and if the retry should happen at all.

Use case:

  • Use retry for simple retry scenarios where you want to retry a fixed number of times after an error.
  • Use retryWhen for more complex retry strategies, such as delaying retries, exponential backoff, or conditional retries based on specific error types.

Example using retry:

import { retry } from 'rxjs';

 

this.http$.pipe(

  retry(3) // Retry up to 3 times in case of an error

).subscribe(result => console.log(result));

Example using retryWhen:

import { retryWhen, delay, take, concatMap } from 'rxjs';

 

this.http$.pipe(

  retryWhen(errors =>

    errors.pipe(

      concatMap((e, i) => i < 3 ? of(e).pipe(delay(1000)) : throwError(e))

    )

  )

).subscribe(result => console.log(result));


67. What is timeout in RxJS and how do you handle a timeout?


The timeout operator is used to throw an error if the source Observable does not emit a value within a specified time period. It is commonly used to handle situations where you expect an Observable to emit values within a certain time frame, like network requests or long-running operations.

Use case: Use timeout to avoid waiting indefinitely for a response and to handle timeout errors in a more controlled way.

Example:

import { timeout, throwError } from 'rxjs';

 

this.http$.pipe(

  timeout(5000) // Timeout after 5 seconds if no value is emitted

).subscribe({

  next: value => console.log('Value received:', value),

  error: err => console.log('Error:', err) // Handle timeout error

});


68. What is shareReplay and how does it help in caching?


The shareReplay operator ensures that multiple subscribers to an Observable receive the most recent emitted value, even if they subscribe at different times. It caches the most recent value (or a specified number of values) and replays them to new subscribers.

Use case: Use shareReplay when you need to cache data (e.g., HTTP responses) and avoid making multiple network requests for the same data.

Example:

import { shareReplay } from 'rxjs';

 

const shared$ = this.http$.pipe(

  shareReplay(1) // Cache the most recent value and replay it to new subscribers

);

 

shared$.subscribe(data => {

  console.log('Subscriber 1:', data); // Receives the cached data

});

shared$.subscribe(data => {

  console.log('Subscriber 2:', data); // Receives the cached data as well

});


69. What is zip in RxJS?


The zip operator combines the emissions of multiple Observables into a single Observable. It waits for all of the provided Observables to emit at least one value, and then it combines their emissions into an array (or custom function) and emits the combined values as a new array.

Use case: Use zip when you want to combine multiple Observables and handle the values from all of them in a synchronized way.

Example:

import { zip } from 'rxjs';

 

zip(this.observable1$, this.observable2$).subscribe(([value1, value2]) => {

  console.log('Combined values:', value1, value2);

});


70. What is switchMapTo in RxJS?


The switchMapTo operator is similar to switchMap, but instead of mapping the source value to an Observable, it simply switches to a given Observable. It allows you to map the source value to an Observable without using that value.

Use case: Use switchMapTo when you want to switch to a fixed Observable when the source emits, without needing to map the source value to a new Observable.

Example:

import { switchMapTo } from 'rxjs';

 

this.source$.pipe(

  switchMapTo(this.httpClient.get('/api/data')) // Switch to the Observable returned by the HTTP request

).subscribe(response => {

  console.log('Response:', response);

});


71. What is toPromise in RxJS, and how does it differ from firstValueFrom and lastValueFrom?

 

  • toPromise: Converts an Observable into a Promise. It waits for the first emitted value and resolves the Promise with that value.
  • firstValueFrom: Converts an Observable to a Promise, but explicitly resolves with the first value emitted by the Observable. It works similarly to toPromise, but it’s part of the rxjs package and recommended for new code.
  • lastValueFrom: Converts an Observable into a Promise that resolves with the last emitted value.

Use case:

  • Use toPromise or firstValueFrom when you need to convert an Observable to a Promise for a specific value (e.g., when working with async/await syntax).
  • Use lastValueFrom when you want the Promise to resolve with the last emitted value of the Observable.

Example with firstValueFrom:

import { firstValueFrom } from 'rxjs';

 

async function fetchData() {

  const data = await firstValueFrom(this.http$.pipe(

    take(1)

  ));

  console.log(data);

}


72. What is partition in RxJS and how does it work?


The partition operator splits an Observable into two Observables based on a condition. The first Observable emits values that satisfy the condition, and the second emits values that do not satisfy the condition.

Use case: Use partition when you need to separate data into two streams based on a specific condition, like filtering active vs inactive users.

Example:

import { partition } from 'rxjs';

 

const [active$, inactive$] = partition(this.users$, user => user.isActive);

 

active$.subscribe(user => console.log('Active user:', user));

inactive$.subscribe(user => console.log('Inactive user:', user));


73. What is buffer in RxJS, and how does it differ from bufferCount?

 

  • buffer: Collects values from the source Observable into an array and emits the array whenever another Observable emits a value (the notifier). The values are buffered until the notifier emits.
  • bufferCount: Collects values into an array and emits it after a specified number of values have been collected.

Use case: Use buffer when you want to buffer emissions based on another Observable’s emissions, and use bufferCount when you want to collect a fixed number of values into an array.

Example using buffer:

import { buffer } from 'rxjs';

 

this.source$.pipe(

  buffer(this.otherSource$) // Buffer values until `otherSource$` emits

).subscribe(values => {

  console.log('Buffered values:', values);

});

Example using bufferCount:

import { bufferCount } from 'rxjs';

 

this.source$.pipe(

  bufferCount(3) // Buffer 3 items and emit them as an array

).subscribe(values => {

  console.log('Buffered values:', values);

});


74. What is finalize in RxJS, and how is it different from complete?


The finalize operator is executed when an Observable completes or errors. It allows you to execute some final logic (like cleanup) regardless of whether the Observable successfully completes or errors.

  • complete: Is a notification sent by an Observable to indicate that it has completed and will emit no further values.
  • finalize: Is called after the Observable completes or errors. It’s useful for cleanup operations (e.g., stopping loading spinners).

Use case: Use finalize when you need to perform final operations like hiding a loading indicator, logging, or cleanup tasks.

Example:

import { finalize } from 'rxjs';

 

this.http$.pipe(

  finalize(() => {

    console.log('Request completed or failed!');

  })

).subscribe();


75. What is takeLast in RxJS, and how does it work?


The takeLast operator emits the last n values emitted by the source Observable before completing. This is useful when you want to retrieve only the last few emitted values.

Use case: Use takeLast when you are only interested in the last few emitted values from a stream.

Example:

import { takeLast } from 'rxjs';

 

this.source$.pipe(

  takeLast(3) // Take the last 3 emitted values

).subscribe(value => {

  console.log('Last value:', value);

});


76. What is ignoreElements in RxJS?


The ignoreElements operator ignores all emissions from the source Observable and only lets notifications (complete or error) propagate. It is useful when you care only about completion or error, and you don’t need the actual emitted values.

Use case: Use ignoreElements when you don’t care about the emitted values but just need to react to completion or error notifications.

Example:

import { ignoreElements } from 'rxjs';

 

this.source$.pipe(

  ignoreElements() // Ignore emitted values, but still complete or error

).subscribe({

  complete: () => console.log('Source Observable completed'),

  error: (err) => console.log('Error:', err)

});


77. What is pluck in RxJS?


The pluck operator extracts a specific property from each emitted value, returning an Observable of the values of that property. This is especially useful when working with objects.

Use case: Use pluck when you want to extract specific properties from an object emitted by the source Observable.

Example:

import { pluck } from 'rxjs';

 

this.users$.pipe(

  pluck('name') // Extract the `name` property from each emitted user object

).subscribe(name => {

  console.log('User name:', name);

});


78. What is auditTime in RxJS, and how does it differ from debounceTime?

 

  • auditTime: Emits the most recent value from the source Observable after a specified time period, but it ignores any new emissions while the timer is running. After the specified period, it emits the latest value.
  • debounceTime: Emits the last value emitted by the source Observable after a period of inactivity. If there is a new value before the debounce time finishes, it resets the timer.

Use case:

  • Use auditTime when you want to emit the most recent value at fixed intervals, even if new values are being emitted before the interval completes.
  • Use debounceTime when you want to wait until the user stops emitting values for a specified time (e.g., for live search).

Example using auditTime:

import { auditTime } from 'rxjs';

 

this.source$.pipe(

  auditTime(500) // Emit the most recent value every 500ms

).subscribe(value => {

  console.log('Emitted:', value);

});


79. What is withLatestFrom in RxJS?


The withLatestFrom operator combines the latest value from another Observable with the values from the source Observable. It allows you to create a stream that includes values from both the source and the provided Observable.

Use case: Use withLatestFrom when you want to merge the latest value from one stream with another stream of values.

Example:

import { withLatestFrom } from 'rxjs';

 

this.click$.pipe(

  withLatestFrom(this.latestData$) // Combine click events with the latest data

).subscribe(([click, data]) => {

  console.log('Click event:', click, 'Latest data:', data);

});


80. What is expand in RxJS?


The expand operator is used for recursive processing. It applies a function to the value emitted by the source Observable and returns an Observable. This Observable can emit further values, which are then passed through the function recursively.

Use case: Use expand when you want to recursively apply a function to a value until a condition is met, for example, paginating through an API.

Example:

import { expand, takeWhile } from 'rxjs';

 

this.page$.pipe(

  expand(page => this.loadPage(page + 1)), // Recursively load next page

  takeWhile(page => page <= 5) // Stop after 5 pages

).subscribe(page => {

  console.log('Loading page:', page);

});


81. What is concatMap in RxJS, and how is it different from mergeMap?

 

  • concatMap: Transforms values from the source Observable by mapping them to inner Observables. It subscribes to each inner Observable one at a time, ensuring that each one completes before moving on to the next. This guarantees sequential execution.
  • mergeMap: Also maps values from the source Observable to inner Observables, but subscribes to all of them concurrently, emitting values as they arrive from the inner Observables.

Use case:

  • Use concatMap when the order of execution is important, and you need to process inner Observables sequentially (e.g., when submitting forms one at a time).
  • Use mergeMap when you don’t care about the order and want concurrent execution for efficiency (e.g., making multiple HTTP requests simultaneously).

Example using concatMap:

import { concatMap } from 'rxjs';

 

this.source$.pipe(

  concatMap(value => this.fetchData(value)) // Sequential processing of each value

).subscribe(result => {

  console.log('Processed sequentially:', result);

});

Example using mergeMap:

import { mergeMap } from 'rxjs';

 

this.source$.pipe(

  mergeMap(value => this.fetchData(value)) // Concurrent processing of each value

).subscribe(result => {

  console.log('Processed concurrently:', result);

});


82. What is retryWhen in RxJS, and how does it differ from retry?

 

  • retryWhen: Allows you to define a custom retry strategy by providing a function that takes an error Observable and returns an Observable that determines when the retry should happen. You can include backoff strategies, delays, and conditions.
  • retry: A simpler operator that automatically retries the Observable a fixed number of times without any custom logic or delay.

Use case:

  • Use retry for straightforward retry logic where you want to retry a fixed number of times on error.
  • Use retryWhen when you need more control over the retry behavior, such as adding delays or handling specific error types.

Example using retry:

import { retry } from 'rxjs';

 

this.http$.pipe(

  retry(3) // Retry the operation 3 times in case of error

).subscribe({

  next: result => console.log(result),

  error: err => console.log('Error:', err)

});

Example using retryWhen:

import { retryWhen, delay, concatMap } from 'rxjs';

 

this.http$.pipe(

  retryWhen(errors =>

    errors.pipe(

      concatMap((error, index) => index < 3 ? of(error).pipe(delay(1000)) : throwError(error))

    )

  )

).subscribe({

  next: result => console.log(result),

  error: err => console.log('Error:', err)

});


83. What is zipAll in RxJS and how does it differ from combineLatest?

 

  • zipAll: Converts an Observable of Observables into an Observable that emits arrays of values, where each array corresponds to the emitted values from the inner Observables at the same index.
  • combineLatest: Emits the latest values from multiple Observables as they emit, without waiting for them to emit at the same time. It emits a new value every time any of the Observables emits.

Use case:

  • Use zipAll when you want to combine values from multiple Observables but only emit them when each Observable has emitted its corresponding value. It’s useful for synchronizing emissions from multiple streams.
  • Use combineLatest when you want to combine the latest emitted values from each stream, regardless of when they were emitted.

Example using zipAll:

import { zipAll } from 'rxjs';

 

const observable1$ = of(1, 2, 3);

const observable2$ = of('a', 'b', 'c');

 

observable1$.pipe(

  zipAll() // Combines values at the same index from all inner Observables

).subscribe(([value1, value2]) => {

  console.log(value1, value2);

});


84. What is exhaustMap in RxJS?


The exhaustMap operator is used to map the values emitted by the source Observable to inner Observables, but it ignores any subsequent values while the inner Observable is still active. In other words, it "exhausts" all emissions from the source Observable by ignoring new emissions until the current inner Observable completes.

Use case: Use exhaustMap when you want to process the first value from the source and ignore subsequent values until the current operation completes (e.g., for form submissions or API calls that should not be triggered multiple times).

Example:

import { exhaustMap } from 'rxjs';

 

this.click$.pipe(

  exhaustMap(() => this.makeRequest()) // Ignore subsequent clicks while a request is ongoing

).subscribe(response => {

  console.log('Response received:', response);

});


85. What is takeUntil in RxJS?


The takeUntil operator is used to take values from the source Observable until a notifier Observable emits a value. After the notifier emits, the source Observable completes.

Use case: Use takeUntil to stop the subscription when a specific event occurs, such as when a user navigates away or when a timeout occurs.

Example:

import { takeUntil } from 'rxjs';

 

this.source$.pipe(

  takeUntil(this.stop$) // Stop emitting values when `stop$` emits

).subscribe(value => {

  console.log(value);

});


86. What is fromEvent in RxJS and how do you use it?


The fromEvent operator creates an Observable that listens for events of a specific type on a given DOM element or Node. This allows you to handle events such as clicks, keypresses, or mouse movements in a declarative way.

Use case: Use fromEvent when you need to handle DOM events reactively (e.g., handling user input or mouse events).

Example:

import { fromEvent } from 'rxjs';

 

const button = document.querySelector('button');

fromEvent(button, 'click').subscribe(() => {

  console.log('Button clicked');

});


87. What is combineAll in RxJS?


The combineAll operator takes an Observable of Observables and combines all the values from the inner Observables into a single Observable. It waits for all inner Observables to complete and then emits an array of the last emitted values.

Use case: Use combineAll when you have an Observable of Observables and you need to gather the final emitted values from each inner Observable into an array after all have completed.

Example:

import { combineAll } from 'rxjs';

 

const observableOfObservables$ = of(of(1, 2), of(3, 4));

 

observableOfObservables$.pipe(

  combineAll() // Combine all emitted values from the inner Observables

).subscribe(values => {

  console.log(values); // [2, 4]

});


88. What is race in RxJS?


The race operator takes multiple Observables and emits values from the first Observable to emit a value. It "races" through the Observables and subscribes to the first one that emits, then ignores the rest.

Use case: Use race when you want to choose between multiple competing sources of data and only care about the first one to emit.

Example:

import { race, of } from 'rxjs';

 

const observable1$ = of('A').pipe(delay(1000));

const observable2$ = of('B').pipe(delay(500));

 

race(observable1$, observable2$).subscribe(value => {

  console.log(value); // 'B' because it emitted first

});


89. What is window in RxJS?


The window operator emits an Observable that contains the values from the source Observable as its "window" of emitted values. It opens a new "window" each time the source emits, and the window emits the values from the source.

Use case: Use window when you want to group values into multiple Observables (windows), allowing you to process them separately.

Example:

import { window, map } from 'rxjs';

 

this.source$.pipe(

  window(this.window$), // Group values based on another Observable's emissions

  map(window$ => window$.toArray()) // Convert each window to an array of values

).subscribe(values => {

  console.log('Window values:', values);

});


90. What is debounceTime in RxJS, and when should you use it?


The debounceTime operator ensures that a value is only emitted after the source Observable has been silent for a specified amount of time. It is typically used to delay emissions and prevent rapid, repeated actions, such as user keystrokes.

Use case: Use debounceTime for scenarios where you want to wait until the user stops typing or an event stops firing before performing an action (e.g., in search bars or form validations).

Example:

import { debounceTime } from 'rxjs';

 

this.searchInput$.pipe(

  debounceTime(300) // Wait for 300ms of silence before emitting the latest value

).subscribe(value => {

  console.log('Search query:', value);

});


91. What is catchError in RxJS, and how is it used?


The catchError operator is used to catch errors that occur during the stream's execution and allows you to handle or recover from those errors. It catches errors emitted by the source Observable and provides an alternative Observable (a fallback stream).

Use case: Use catchError when you want to handle errors in a stream, such as providing a default value or retrying the operation.

Example:

import { catchError } from 'rxjs';

 

this.http$.pipe(

  catchError(err => {

    console.error('Error:', err);

    return of('Fallback value'); // Return an observable with a fallback value

  })

).subscribe(result => {

  console.log('Result:', result); // 'Fallback value' in case of error

});


92. What is tap in RxJS, and how does it differ from map?

 

  • tap: The tap operator is a side-effect operator. It allows you to perform actions (like logging or debugging) on the emitted values without modifying them. It does not alter the stream and simply passes the values through unchanged.
  • map: The map operator is used to transform the emitted values by applying a function to each value, creating a new value.

Use case:

  • Use tap for side effects like logging, debugging, or triggering actions that do not affect the stream’s flow.
  • Use map when you need to transform the emitted value before passing it along.

Example using tap:

import { tap } from 'rxjs';

 

this.source$.pipe(

  tap(value => console.log('Side effect:', value)) // Log values without changing them

).subscribe();


93. What is pairwise in RxJS?


The pairwise operator emits an array of two consecutive values from the source Observable. It will emit the previous and current value as an array each time a new value is emitted.

Use case: Use pairwise when you need to compare consecutive values from a stream, like calculating changes in data or comparing the previous and current values in a stream.

Example:

import { pairwise } from 'rxjs';

 

this.source$.pipe(

  pairwise() // Emit consecutive pairs of values

).subscribe(([prev, curr]) => {

  console.log('Previous:', prev, 'Current:', curr);

});


94. What is shareReplay in RxJS?


The shareReplay operator multicasts the source Observable and shares the emitted values among multiple subscribers. It also caches the most recent emitted values, replaying them to new subscribers when they subscribe, based on a specified buffer size.

Use case: Use shareReplay when you want to share the result of an Observable and avoid making repeated requests or re-running expensive operations.

Example:

import { shareReplay } from 'rxjs';

 

this.http$.pipe(

  shareReplay(1) // Cache the most recent value and share it with new subscribers

).subscribe(result => {

  console.log('Result:', result);

});


95. What is mergeAll in RxJS?


The mergeAll operator subscribes to each inner Observable emitted by the source Observable concurrently, and emits all values from those inner Observables in the order they arrive.

Use case: Use mergeAll when you have an Observable that emits Observables and you want to merge all the emissions from these inner Observables into a single stream.

Example:

import { mergeAll } from 'rxjs';

 

this.source$.pipe(

  mergeAll() // Merge values from all emitted Observables

).subscribe(value => {

  console.log('Merged value:', value);

});


96. What is groupBy in RxJS?


The groupBy operator groups the emissions from the source Observable based on a key. It emits a grouped Observable for each distinct key, which you can then process individually.

Use case: Use groupBy when you want to group items based on some criteria and then process each group separately (e.g., grouping users by their city).

Example:

import { groupBy, mergeMap, map } from 'rxjs';

 

this.users$.pipe(

  groupBy(user => user.city), // Group users by city

  mergeMap(group$ => group$.pipe(

    map(user => user.name)

  )) // Process each group

).subscribe(name => {

  console.log('User name:', name);

});


97. What is takeWhile in RxJS, and how does it work?


The takeWhile operator emits values from the source Observable as long as a specified condition is true. Once the condition becomes false, it completes the stream.

Use case: Use takeWhile when you need to filter the stream until a certain condition is met, such as stopping data collection after a specific value.

Example:

import { takeWhile } from 'rxjs';

 

this.source$.pipe(

  takeWhile(value => value < 10) // Take values until the value is no longer less than 10

).subscribe(value => {

  console.log(value);

});


98. What is debounce in RxJS, and how does it differ from debounceTime?

 

  • debounceTime: Waits for a specific duration of inactivity before emitting the most recent value. It is typically used for scenarios like waiting for a user to stop typing in a search bar before firing an API request.
  • debounce: Similar to debounceTime, but instead of waiting for a fixed duration, it waits for an Observable (often based on a time-based condition) to emit before continuing. It provides more flexibility, like custom delays or timeouts.

Use case:

  • Use debounceTime for simple debounce scenarios with a fixed delay.
  • Use debounce for more complex scenarios where the debounce condition is dynamic.

Example using debounce:

import { debounce } from 'rxjs';

 

this.source$.pipe(

  debounce(() => this.getDebounceDelay()) // Custom debounce logic based on another Observable

).subscribe(value => {

  console.log('Debounced value:', value);

});


99. What is retry in RxJS, and how does it work?


The retry operator retries the source Observable a specified number of times when it encounters an error. If the Observable still errors after the specified number of retries, the error will propagate.

Use case: Use retry when you want to automatically retry an operation a certain number of times before propagating the error, such as retrying a failed network request.

Example:

import { retry } from 'rxjs';

 

this.http$.pipe(

  retry(3) // Retry the request 3 times if it fails

).subscribe({

  next: result => console.log('Result:', result),

  error: err => console.log('Error:', err)

});


100. What is defaultIfEmpty in RxJS?


The defaultIfEmpty operator emits a default value if the source Observable completes without emitting any values. This can be useful when you want to ensure that a value is emitted even when the source Observable is empty.

Use case: Use defaultIfEmpty when you want to provide a fallback value if the Observable completes without emitting anything.

Example:

import { defaultIfEmpty } from 'rxjs';

 

this.source$.pipe(

  defaultIfEmpty('No values emitted') // Emit a default value if the source is empty

).subscribe(value => {

  console.log(value); // 'No values emitted' if the source is empty

});


101. What is from in RxJS, and when would you use it?


The from operator is used to convert various types of data (arrays, promises, iterables, or observables) into an Observable. It enables handling non-Observable data in a reactive manner.

Use case: Use from when you need to convert an array, promise, or other iterable to an Observable to work with it reactively.

Example:

import { from } from 'rxjs';

 

// Convert an array into an Observable

from([1, 2, 3]).subscribe(value => {

  console.log(value); // 1, 2, 3

});

 

// Convert a promise into an Observable

from(Promise.resolve('Hello')).subscribe(value => {

  console.log(value); // 'Hello'

});


102. What is switchAll in RxJS?


The switchAll operator subscribes to each Observable emitted by the source Observable. It cancels the previous inner Observable whenever a new inner Observable is emitted, making it useful for scenarios where only the latest inner Observable’s emissions matter.

Use case: Use switchAll when you need to switch to a new inner Observable and cancel the previous one, such as in search auto-completion or live updates where only the latest result is needed.

Example:

import { switchAll, map, of } from 'rxjs';

 

this.search$.pipe(

  map(query => this.searchApi(query)), // Emits an Observable from the API

  switchAll() // Switch to the latest search Observable and cancel previous ones

).subscribe(result => {

  console.log(result); // Latest search result

});


103. What is concatAll in RxJS, and when should you use it?


The concatAll operator subscribes to each Observable emitted by the source Observable one at a time, ensuring that it processes them sequentially (i.e., the next Observable starts only after the previous one completes).

Use case: Use concatAll when you need to sequentially process multiple Observables, ensuring that one completes before the next one starts (e.g., processing a batch of tasks in sequence).

Example:

import { concatAll } from 'rxjs';

 

this.source$.pipe(

  concatAll() // Process all emitted Observables sequentially

).subscribe(result => {

  console.log(result); // Sequentially processed values

});


104. What is bufferTime in RxJS?


The bufferTime operator collects values emitted by the source Observable into an array, which is emitted after a specified period of time. It works by "buffering" values over a time interval and emitting them as an array when the time window is complete.

Use case: Use bufferTime when you need to collect values over a period and then emit them as an array after the time window elapses, such as gathering a set of values for batch processing.

Example:

import { bufferTime } from 'rxjs';

 

this.source$.pipe(

  bufferTime(2000) // Collect values every 2 seconds into an array

).subscribe(values => {

  console.log(values); // Array of values emitted every 2 seconds

});


105. What is expand in RxJS?


The expand operator recursively projects each value from the source Observable into a new Observable, then subscribes to that new Observable and repeats the process until a condition is met. It's like map, but it works recursively to emit new values over time.

Use case: Use expand when you need to generate a recursive series of values (like pagination or tree traversal) based on previous values.

Example:

import { expand, takeWhile } from 'rxjs';

 

this.source$.pipe(

  expand(value => this.getNextValue(value)), // Recursively call getNextValue

  takeWhile(value => value < 10) // Stop the recursion once the value reaches 10

).subscribe(result => {

  console.log(result); // Recursively emitted values

});


106. What is first in RxJS?


The first operator emits the first value from the source Observable that meets a given condition. If no condition is provided, it emits the first value emitted by the source. If no value is emitted, it can return a default value or throw an error.

Use case: Use first when you only care about the first value emitted by the Observable or when you need to limit emissions to just the first valid value.

Example:

import { first } from 'rxjs';

 

this.source$.pipe(

  first(value => value > 5, 'No value found') // Emit the first value greater than 5, or a default

).subscribe(result => {

  console.log(result); // The first value greater than 5, or 'No value found'

});


107. What is combineLatestWith in RxJS?


The combineLatestWith operator combines the emissions of the source Observable with those of another Observable. It emits the latest values from both Observables every time either of them emits.

Use case: Use combineLatestWith when you want to combine the latest values from multiple streams and react to changes in any of them.

Example:

import { combineLatestWith, of } from 'rxjs';

 

this.source$.pipe(

  combineLatestWith(of('A', 'B')) // Combine values from source$ and an array of values

).subscribe(([sourceValue, combinedValue]) => {

  console.log('Source:', sourceValue, 'Combined:', combinedValue);

});


108. What is finalize in RxJS?


The finalize operator allows you to perform cleanup actions (like closing resources or logging) when an Observable completes or errors. It will always be executed regardless of whether the Observable successfully completes or emits an error.

Use case: Use finalize for cleanup tasks that need to occur regardless of the completion state of the Observable (e.g., stopping loading indicators, closing connections).

Example:

import { finalize } from 'rxjs';

 

this.source$.pipe(

  finalize(() => console.log('Observable has completed or errored'))

).subscribe({

  next: value => console.log(value),

  error: err => console.log('Error:', err)

});


109. What is raceWith in RxJS?


The raceWith operator is used to subscribe to two or more Observables and emit values from the first Observable that emits a value. It "races" the Observables and whichever emits first wins.

Use case: Use raceWith when you want to handle multiple competing Observables and react to the first one that emits.

Example:

import { raceWith, of, timer } from 'rxjs';

 

const source$ = timer(1000);

const race$ = of('First wins!');

 

source$.pipe(

  raceWith(race$) // race against `race$` and emit the first one to win

).subscribe(result => {

  console.log(result); // 'First wins!' because `race$` emits first

});


110. What is throttleTime in RxJS, and how does it differ from debounceTime?

 

  • throttleTime: Emits the first value from the source Observable, then ignores all subsequent values for a specified duration. It essentially "throttles" the stream, ensuring that emissions are spaced out.
  • debounceTime: Waits for a period of inactivity after the last emitted value before emitting the most recent value.

Use case:

  • Use throttleTime when you want to emit a value at regular intervals, ensuring that rapid emissions are ignored.
  • Use debounceTime when you want to wait for silence before emitting the latest value (useful in search bars or typeahead features).

Example using throttleTime:

import { throttleTime } from 'rxjs';

 

this.source$.pipe(

  throttleTime(1000) // Emit only the first value in every 1-second interval

).subscribe(value => {

  console.log(value); // First value every 1 second

});


111. What is bufferCount in RxJS?


The bufferCount operator collects values from the source Observable in batches of a specified size and emits them as an array when the batch is complete.

Use case: Use bufferCount when you want to collect values into chunks and process them in groups rather than individually (e.g., batching requests).

Example:

import { bufferCount } from 'rxjs';

 

this.source$.pipe(

  bufferCount(3) // Group values into batches of 3

).subscribe(values => {

  console.log(values); // Array of values in batches of 3

});


112. What is startWith in RxJS?


The startWith operator allows you to prepend an initial value to the source Observable’s emissions. It emits the specified value before the source Observable starts emitting.

Use case: Use startWith when you need to provide an initial value, such as when you want to provide a loading state before actual data is emitted.

Example:

import { startWith } from 'rxjs';

 

this.source$.pipe(

  startWith('Loading...') // Emit 'Loading...' before any values from the source

).subscribe(value => {

  console.log(value); // 'Loading...' first, then source values

});


113. What is zip in RxJS and how does it work?


The zip operator combines multiple Observables by taking one value from each Observable and then emitting them as an array. It waits until each of the source Observables has emitted at least one value before emitting a combined result.

Use case: Use zip when you need to combine the latest values from multiple Observables, but only when each has emitted at least one value.

Example:

import { zip, of } from 'rxjs';

 

const observable1 = of('A', 'B', 'C');

const observable2 = of(1, 2, 3);

 

zip(observable1, observable2).subscribe(([val1, val2]) => {

  console.log(val1, val2); // ['A', 1], ['B', 2], ['C', 3]

});


114. What is takeUntil in RxJS, and when should it be used?


The takeUntil operator emits values from the source Observable until a notifier Observable emits its first value. After that, it completes the source Observable.

Use case: Use takeUntil when you want to unsubscribe from an Observable based on an event or condition from another Observable, such as stopping a stream when a user logs out or when a certain time elapses.

Example:

import { takeUntil, timer } from 'rxjs';

 

const stopNotifier$ = timer(5000); // Emits after 5 seconds

this.source$.pipe(

  takeUntil(stopNotifier$) // Stop emitting from source$ after 5 seconds

).subscribe(value => {

  console.log(value); // Will stop after 5 seconds

});


115. What is auditTime in RxJS, and how is it different from throttleTime?

 

  • auditTime: Emits the most recent value from the source Observable after a specified time interval, but only emits once during each interval regardless of the number of emitted values.
  • throttleTime: Emits the first value from the source Observable and then ignores subsequent emissions for the specified duration, effectively "throttling" the flow.

Use case: Use auditTime when you want to "take a snapshot" of the source Observable periodically, but don't care about intermediate emissions during that time.

Example:

import { auditTime } from 'rxjs';

 

this.source$.pipe(

  auditTime(1000) // Emit the most recent value once every 1 second

).subscribe(value => {

  console.log(value); // Latest value every 1 second

});


116. What is concatMap in RxJS, and how does it differ from mergeMap?

 

  • concatMap: It projects each value from the source Observable into an inner Observable and subscribes to them sequentially. It waits for each inner Observable to complete before subscribing to the next one.
  • mergeMap: It projects each value from the source Observable into an inner Observable and subscribes to them concurrently, without waiting for each inner Observable to complete.

Use case: Use concatMap when you need to process inner Observables sequentially. Use mergeMap when you need to handle multiple inner Observables concurrently.

Example with concatMap:

import { concatMap, of } from 'rxjs';

 

this.source$.pipe(

  concatMap(value => of(value).pipe(delay(1000))) // Process values sequentially

).subscribe(value => {

  console.log(value); // Processed one at a time

});


117. What is debounce in RxJS and how does it differ from debounceTime?

 

  • debounceTime: It waits for a specific time of inactivity (no emissions) before emitting the most recent value.
  • debounce: It waits for a custom Observable to emit a value before emitting the most recent source value. The delay is based on a dynamic Observable rather than a fixed time.

Use case: Use debounce when you need to apply a custom debounce logic that depends on an external factor or condition, instead of just waiting for a fixed delay.

Example:

import { debounce, timer } from 'rxjs';

 

this.source$.pipe(

  debounce(() => timer(500)) // Wait for 500ms after the last emission before emitting

).subscribe(value => {

  console.log(value); // Latest value after custom debounce

});


118. What is distinctUntilChanged in RxJS?


The distinctUntilChanged operator ensures that only distinct consecutive values are emitted from the source Observable. If the value is the same as the previous emission, it will not emit again.

Use case: Use distinctUntilChanged when you want to skip emitting values that are the same as the previous one, such as in user input scenarios where you only want to process changes.

Example:

import { distinctUntilChanged } from 'rxjs';

 

this.source$.pipe(

  distinctUntilChanged() // Only emit if the current value is different from the previous one

).subscribe(value => {

  console.log(value); // Only distinct consecutive values will be logged

});


119. What is repeatWhen in RxJS, and when would you use it?


The repeatWhen operator allows you to specify a condition under which an Observable will repeat itself. It takes a function that returns an Observable, and once that Observable emits a value, the source Observable will resubscribe and start emitting again.

Use case: Use repeatWhen when you want to restart an Observable stream based on a custom condition, such as retrying an operation after a delay or conditionally repeating the stream.

Example:

import { repeatWhen, delay } from 'rxjs';

 

this.source$.pipe(

  repeatWhen(notifications => notifications.pipe(delay(1000))) // Resubscribe after 1 second delay

).subscribe(value => {

  console.log(value); // The stream will repeat after each notification

});


120. What is fromEvent in RxJS, and how is it useful?


The fromEvent operator creates an Observable from DOM events or any event-based APIs. It listens for events like clicks, mouse movements, keypresses, etc., and emits those events as values in the stream.

Use case: Use fromEvent when you need to listen to user interactions (like button clicks) or other event-driven sources.

Example:

import { fromEvent } from 'rxjs';

 

const button = document.getElementById('myButton');

fromEvent(button, 'click').subscribe(event => {

  console.log('Button clicked!', event);

});


121. What is mergeMap in RxJS, and how does it differ from switchMap?

 

  • mergeMap: It subscribes to each inner Observable concurrently and emits values from all of them as they arrive, regardless of order.
  • switchMap: It switches to the latest inner Observable and cancels any previous ones. It emits values only from the latest inner Observable.

Use case: Use mergeMap when you need to handle concurrent inner Observables. Use switchMap when you need to discard the result of a previous Observable when a new one is emitted (e.g., search-as-you-type).

Example with mergeMap:

import { mergeMap } from 'rxjs';

 

this.source$.pipe(

  mergeMap(value => this.http.get(`https://api.example.com/${value}`))

).subscribe(response => {

  console.log(response); // Response from each API call

});


122. What is repeat in RxJS?


The repeat operator causes the source Observable to resubscribe and restart the emission of values a specified number of times. After the specified number of repetitions, the Observable will complete.

Use case: Use repeat when you want to repeat the source stream a certain number of times, useful in scenarios where you want to retry an operation a few times before stopping.

Example:

import { repeat } from 'rxjs';

 

this.source$.pipe(

  repeat(3) // Repeat the source stream 3 times

).subscribe(value => {

  console.log(value); // Repeats the values 3 times

});


123. What is finalize in RxJS, and when is it triggered?


The finalize operator is used to perform cleanup logic, such as stopping loading spinners or releasing resources, when an Observable completes or errors out. It is executed when the Observable terminates, regardless of whether it completes or errors.

Use case: Use finalize for performing any cleanup tasks, like logging out, stopping a loading spinner, or resetting application state.

Example:

import { finalize } from 'rxjs';

 

this.source$.pipe(

  finalize(() => console.log('Cleanup after stream is completed or errored'))

).subscribe({

  next: value => console.log(value),

  error: err => console.error(err)

});


124. What is share in RxJS?


The share operator is a multicast operator that makes the source Observable shared among multiple subscribers. It essentially creates a "hot" Observable, meaning that multiple subscribers will share the same underlying stream, and the Observable will not be re-executed for each subscription.

Use case: Use share when you want to ensure that multiple subscribers are receiving the same data without creating separate executions of the Observable.

Example:

import { of, share } from 'rxjs';

 

const source$ = of('A', 'B', 'C').pipe(share());

 

source$.subscribe(value => console.log('Subscriber 1:', value));

source$.subscribe(value => console.log('Subscriber 2:', value));

Both subscribers will share the same source without re-running the logic.


125. What is take in RxJS, and how does it work?


The take operator limits the number of emissions from the source Observable. It will take only a specified number of values from the source Observable and then automatically complete the stream.

Use case: Use take when you want to limit the number of emitted values or process just the first few emissions.

Example:

import { take } from 'rxjs';

 

this.source$.pipe(

  take(3) // Take only the first 3 values and then complete

).subscribe(value => {

  console.log(value); // Only the first 3 values will be emitted

});


126. What is catchError in RxJS, and how do you handle errors with it?


The catchError operator is used for handling errors in an Observable stream. It allows you to catch and recover from errors by returning a new Observable or a fallback value when an error occurs.

Use case: Use catchError when you want to handle errors within your stream, either by providing an alternative stream or a fallback value.

Example:

import { catchError, of } from 'rxjs';

 

this.source$.pipe(

  catchError(error => {

    console.error('Error:', error);

    return of('Fallback value'); // Return a fallback value on error

  })

).subscribe(value => {

  console.log(value); // 'Fallback value' if an error occurs

});


127. What is exhaustMap in RxJS, and when would you use it?


The exhaustMap operator projects each value from the source Observable into an inner Observable. However, if a new value arrives while the inner Observable is still executing, it will ignore the new value and continue with the current one. It "exhausts" the source Observable's values until the inner Observable completes.

Use case: Use exhaustMap when you want to process values one by one, ignoring new emissions while processing an ongoing operation (e.g., form submissions or authentication).

Example:

import { exhaustMap } from 'rxjs';

 

this.source$.pipe(

  exhaustMap(value => this.apiRequest(value)) // Ignore new values while the request is in progress

).subscribe(result => {

  console.log(result);

});


128. What is mergeAll in RxJS?


The mergeAll operator is used when you have an Observable of Observables, and you want to merge the emissions of each inner Observable into a single stream. It subscribes to each inner Observable and emits their values concurrently.

Use case: Use mergeAll when you have multiple Observables and you want to combine their emissions without waiting for one to complete before subscribing to the next.

Example:

import { mergeAll } from 'rxjs';

 

this.source$.pipe(

  mergeAll() // Merge multiple Observables emitted by the source into a single stream

).subscribe(value => {

  console.log(value); // Emitting values concurrently from all inner Observables

});


129. What is skipWhile in RxJS?


The skipWhile operator skips emissions from the source Observable as long as they satisfy a provided condition. Once a value does not satisfy the condition, it begins emitting values from that point onward.

Use case: Use skipWhile when you want to discard initial values that meet a condition, and start emitting only when a certain condition is no longer met.

Example:

import { skipWhile } from 'rxjs';

 

this.source$.pipe(

  skipWhile(value => value < 10) // Skip values less than 10

).subscribe(value => {

  console.log(value); // Emit only values greater than or equal to 10

});


130. What is startWith in RxJS, and when should it be used?


The startWith operator emits a specified initial value before any values from the source Observable. This is useful for providing a default value or an initial state before the source Observable emits any data.

Use case: Use startWith when you want to provide an initial value, like setting an initial loading state or providing default data before actual values arrive.

Example:

import { startWith } from 'rxjs';

 

this.source$.pipe(

  startWith('Loading...') // Emit 'Loading...' first before any other values

).subscribe(value => {

  console.log(value); // 'Loading...' first, then the source values

});


131. What is windowTime in RxJS, and how does it work?


The windowTime operator creates a new "window" (a separate Observable) that emits values in time intervals, with the window resetting after each specified time period. It allows you to group values within fixed time windows.

Use case: Use windowTime when you want to group emitted values within time windows for processing.

Example:

import { windowTime } from 'rxjs';

 

this.source$.pipe(

  windowTime(1000) // Group values into windows of 1 second

).subscribe(window$ => {

  window$.subscribe(value => {

    console.log(value); // Values emitted within the 1-second window

  });

});


132. What is concat in RxJS?


The concat operator is used to concatenate multiple Observables together. It subscribes to each Observable in sequence, waiting for one to complete before subscribing to the next one. Each Observable is emitted one after the other, in order.

Use case: Use concat when you want to handle multiple Observables sequentially, ensuring that one completes before the next one starts.

Example:

import { concat, of } from 'rxjs';

 

const source1$ = of('A', 'B');

const source2$ = of('C', 'D');

 

concat(source1$, source2$).subscribe(value => {

  console.log(value); // 'A', 'B', 'C', 'D'

});


133. What is takeWhile in RxJS?


The takeWhile operator emits values from the source Observable as long as they satisfy a specified condition. Once a value no longer satisfies the condition, it will complete the Observable.

Use case: Use takeWhile when you want to continue emitting values until a condition is no longer met, such as when processing values until a certain threshold is reached.

Example:

import { takeWhile } from 'rxjs';

 

this.source$.pipe(

  takeWhile(value => value < 10) // Take values as long as they are less than 10

).subscribe(value => {

  console.log(value); // Values less than 10 will be emitted

});


134. What is pairwise in RxJS?


The pairwise operator collects pairs of consecutive values from the source Observable and emits them as an array. It pairs each value with the value emitted immediately before it.

Use case: Use pairwise when you need to compare consecutive values from the source stream, such as calculating differences or comparing states over time.

Example:

import { pairwise } from 'rxjs';

 

this.source$.pipe(

  pairwise() // Emit pairs of consecutive values as arrays

).subscribe(([prev, current]) => {

  console.log('Previous:', prev, 'Current:', current);

});


135. What is combineLatest in RxJS?


The combineLatest operator combines the latest emissions from multiple Observables and emits them as an array. It waits until each source Observable has emitted at least one value, then emits a combination of the latest values.

Use case: Use combineLatest when you need to combine the latest values from multiple Observables, such as combining user input with server data.

Example:

import { combineLatest, of } from 'rxjs';

 

const source1$ = of('A', 'B');

const source2$ = of(1, 2);

 

combineLatest([source1$, source2$]).subscribe(([val1, val2]) => {

  console.log(val1, val2); // 'B', 2 (latest values from both Observables)

});


136. What is repeatWhen in RxJS?


The repeatWhen operator allows you to specify a condition that triggers the repetition of an Observable. It will resubscribe to the source Observable based on the emissions from the notifier Observable.

Use case: Use repeatWhen when you want to repeat an Observable based on custom logic, such as retrying an HTTP request on failure after a delay.

Example:

import { repeatWhen, delay } from 'rxjs';

 

this.source$.pipe(

  repeatWhen(notifications => notifications.pipe(delay(1000))) // Repeat after 1 second delay

).subscribe(value => {

  console.log(value); // Repeat the stream

});


137. What is concatMapTo in RxJS?


The concatMapTo operator is similar to concatMap, but instead of mapping each value to an inner Observable, it maps each value to the same inner Observable. It is useful when you want to transform each emission to a static Observable.

Use case: Use concatMapTo when you need to emit a constant Observable for each emission from the source Observable, while ensuring that each emission is processed sequentially.

Example:

import { concatMapTo, of } from 'rxjs';

 

this.source$.pipe(

  concatMapTo(of('A', 'B', 'C')) // For every emission from source$, emit 'A', 'B', 'C'

).subscribe(value => {

  console.log(value); // 'A', 'B', 'C' for each emission of source$

});


138. What is bufferCount in RxJS?


The bufferCount operator collects values from the source Observable in buffers of a specified size. Once the buffer is full, it emits the collected values as an array and resets the buffer.

Use case: Use bufferCount when you want to group values into arrays, each containing a fixed number of values, for batch processing or analysis.

Example:

import { bufferCount } from 'rxjs';

 

this.source$.pipe(

  bufferCount(3) // Group the source values into buffers of size 3

).subscribe(buffer => {

  console.log(buffer); // [[1, 2, 3], [4, 5, 6], ...]

});


139. What is shareReplay in RxJS?


The shareReplay operator is used to multicast the source Observable and cache its emitted values, allowing subsequent subscribers to immediately receive the most recent emissions without re-executing the Observable. It "replays" the last emitted values for new subscribers.

Use case: Use shareReplay when you want to share data between multiple subscribers, but don't want to recompute the result or re-fetch data from a server every time.

Example:

import { of, shareReplay } from 'rxjs';

 

const source$ = of('A', 'B', 'C').pipe(shareReplay(2)); // Replay the last 2 values

 

source$.subscribe(value => console.log('Subscriber 1:', value)); // A, B, C

source$.subscribe(value => console.log('Subscriber 2:', value)); // B, C


140. What is windowCount in RxJS?


The windowCount operator divides the source Observable's emissions into fixed-sized "windows" (chunks) of a specified count. It emits each window as a new Observable.

Use case: Use windowCount when you want to process groups of values in windows of fixed size and perform operations on each chunk.

Example:

import { windowCount, take } from 'rxjs';

 

this.source$.pipe(

  windowCount(3), // Create windows of 3 emissions

  take(2) // Take only 2 windows

).subscribe(window$ => {

  window$.subscribe(value => {

    console.log(value); // Values grouped in windows of 3

  });

});


141. What is audit in RxJS, and how does it differ from auditTime?

 

  • audit: Similar to auditTime, but it uses a custom Observable (the auditor) to define the window for emitting the most recent value.
  • auditTime: Uses a fixed time interval for determining when to emit the most recent value.

Use case: Use audit when you want to define the debounce interval dynamically via another Observable, such as using user-defined conditions or events to trigger emissions.

Example with audit:

import { audit, timer } from 'rxjs';

 

this.source$.pipe(

  audit(() => timer(1000)) // Only emit after 1 second of inactivity

).subscribe(value => {

  console.log(value); // Latest value after the defined period

});


142. What is takeLast in RxJS?


The takeLast operator emits the last specified number of values from the source Observable before it completes. It allows you to grab values from the end of the stream.

Use case: Use takeLast when you need to retrieve the last few emitted values from the stream, such as when you only care about the most recent results.

Example:

import { takeLast } from 'rxjs';

 

this.source$.pipe(

  takeLast(2) // Take the last 2 values emitted by the source

).subscribe(value => {

  console.log(value); // The last two emitted values

});


143. What is defaultIfEmpty in RxJS, and when is it used?


The defaultIfEmpty operator emits a specified value if the source Observable completes without emitting any values. This can be useful when you want to provide a fallback or default value in case the Observable stream ends without any emissions.

Use case: Use defaultIfEmpty when you need to handle cases where the Observable may not emit any values, and you want to ensure that a default value is emitted instead.

Example:

import { defaultIfEmpty } from 'rxjs';

 

this.source$.pipe(

  defaultIfEmpty('No data available') // Emit a default value if no values are emitted

).subscribe(value => {

  console.log(value); // 'No data available' if the source is empty

});


144. What is sample in RxJS, and how is it used?


The sample operator emits the latest value from the source Observable at regular intervals based on a "sampler" Observable. The "sampler" Observable triggers the emission, but the value emitted by the source is captured at that point.

Use case: Use sample when you want to periodically sample the most recent value emitted by the source Observable, such as in user interface animations or status updates.

Example:

import { sample, interval } from 'rxjs';

 

this.source$.pipe(

  sample(interval(1000)) // Take the latest value every 1 second

).subscribe(value => {

  console.log(value); // Latest value from the source every second

});


145. What is debounce vs debounceTime in RxJS?

 

  • debounceTime: Emits the most recent value from the source Observable after a fixed delay. It waits for a specified amount of time to pass without new emissions before emitting.
  • debounce: Similar to debounceTime, but it allows you to control the debounce period with a custom Observable. This means the delay period can be dynamically adjusted.

Use case: Use debounce when you want a custom debounce strategy, and debounceTime when you just need a fixed time period for debouncing.

Example with debounce:

import { debounce, timer } from 'rxjs';

 

this.source$.pipe(

  debounce(() => timer(500)) // Wait for 500ms of inactivity before emitting

).subscribe(value => {

  console.log(value); // Emission after 500ms of no activity

});


146. What is switchAll in RxJS?


The switchAll operator subscribes to the first inner Observable emitted by the source Observable. Once the inner Observable completes, it switches to the next one emitted by the source Observable. It cancels any previously active inner Observables.

Use case: Use switchAll when you need to ensure that only the latest emitted inner Observable is active, discarding previous ones.

Example:

import { switchAll } from 'rxjs';

 

this.source$.pipe(

  switchAll() // Subscribe to the latest inner Observable emitted by the source

).subscribe(value => {

  console.log(value); // Only the latest inner Observable is active

});


147. What is finalize in RxJS and when would you use it?


The finalize operator allows you to perform actions when the Observable completes or errors out, regardless of whether it completes normally or throws an error. It is typically used for cleanup operations.

Use case: Use finalize to trigger cleanup tasks, such as hiding loading indicators or stopping timers, after the Observable stream completes or fails.

Example:

import { finalize } from 'rxjs';

 

this.source$.pipe(

  finalize(() => console.log('Stream completed or errored'))

).subscribe({

  next: value => console.log(value),

  error: err => console.error(err)

});


148. What is publishReplay in RxJS, and how does it work?


The publishReplay operator is a combination of the shareReplay and publish operators. It not only shares the Observable but also replays the last emitted values to new subscribers. It’s useful when you want to ensure that new subscribers receive the most recent values.

Use case: Use publishReplay when you want to cache the emitted values and share the Observable among multiple subscribers, ensuring they all get the most recent values.

Example:

import { publishReplay, refCount, of } from 'rxjs';

 

const source$ = of('A', 'B', 'C').pipe(publishReplay(2), refCount()); // Replay the last 2 values

 

source$.subscribe(value => console.log('Subscriber 1:', value)); // 'A', 'B', 'C'

source$.subscribe(value => console.log('Subscriber 2:', value)); // 'B', 'C'

  

Comments

Popular posts from this blog

Multiline to singleline IN C# - CODING

EF Core interview questions for beginners

EF Core interview questions for experienced