RxJS Observables Primer in angular

0

The early days of GUI applications ushered in a new kind of paradigm known as event architecture. Its main characteristic is that the program flow is determined by events such as user actions (mouse clicks, key presses), sensor outputs or messages transmitted by other programs or threads. It was part of Visual Basic, Java and JavaScript (JS). In all these languages, the process is more or less the same: a daemon thread listens for events then triggers a callback function when one of these events is detected.

In today’s responsive web applications, event programming has reached new heights of flexibility and complexity. Aided by libraries like RxJS, events can be triggered by anything from AJAX responses to item loading, complex calculation results, and more. To handle this wide range of event types, RxJS introduced the Observable. In this tutorial, we’ll learn what an observable is and how to use it in the context of your Angular applications.

Learn more about error handling in RxJS.

Flux and observables in RxJS

If you’ve worked in Java before, you might already be familiar with streams. Either way, we’re going to recap what a flow is here so we’re all on the same page. Essentially, a stream is a sequence of data values ​​over time. Data values ​​can be represented by any type, including primitives such as numbers, built-in JS objects such as chains and Appointment, as well as custom classes and / or objects. The key to remember is that data values ​​can be collected over time.

An Observable is a special type of function that can return a stream of values ​​to an observer as they are made available, either synchronously or asynchronously. The stream can never emit a value or produce an infinite number of values ​​during the life of an application. The Observer subscribes to the Observable and provides a callback function that runs whenever the underlying stream emits a value.

The observable life cycle

Since you can have many Observables listening for new values, they can take a lot of resources if not handled with great care. Each observable instance goes through these four stages throughout its lifetime:

  • Creation
  • Subscription
  • Execution
  • Destruction

The next sections cover each stage of the lifecycle in more detail.

Creation and the new keyword

Observables are objects; therefore, they can be instantiated using the New keyword:

import { Observable, Subscriber } from 'rxjs';

const observable = 
  new Observable((subscriber: Subscriber) => {
    subscriber.next('Hello World!');
});

You must transmit a subscriber function. This is the function that is executed when a consumer calls the subscribe () method. The subscriber function defines how to get or generate values ​​or messages to be published. Your function will receive a subscriber that implements the Observer interface and extends the subscription class. The Observer interface includes three useful methods that handle the different types of notifications an observable can send. These are:

  • Following: Obligatory. A manager for each value delivered. Called zero or more times after the start of execution.
  • Fault: Optional. A handler for error notification. An error interrupts the execution of the observable instance.
  • Completed: Optional. A manager for the end of execution notification. Delayed values ​​can continue to be passed to the next handler after execution is complete.

An Observable instance will not start posting values ​​until someone subscribes to it.

The subscription and the subscription () method

You subscribe by calling subscribe () method of the instance, passing a observer object to receiving notifications. Subscribe () receives an object with the three handlers mentioned above, but only Following is required. Here is the signature of the method:

source$.subscribe({ 
  next: doSomething, 
  [error: handleTheError,]
  [complete: wrapItUp]
})

Here is code that implements all three handlers:

observable.subscribe({ 
  next: (message: string) => {
    this.messages.push(message);
    this.message = this.messages.join(', ');
  }, 
  error: (error: string) => {
    console.log(error);
    this.errMsg = error;
  }, 
  complete: () => console.log('All done.')
});

Execution

The observer is responsible for executing the instructions in the observable by providing data, errors, and the signal that transmissions are complete. Once the full value is sent, no new data can be passed to the observable (although lazy data can).

import { Observable, Subscriber } from 'rxjs';

const observable = 
  new Observable((subscriber: Subscriber) => {
    subscriber.next('I am number 1');
    subscriber.next('I am number 2');
    setTimeout(() => {
      subscriber.next('I am number 3');
      subscriber.complete();
    }, 1000);
});

Destruction and the complete () method

It is vitally important that you always call Completed () on your observables when you’re done. Otherwise, you might end up with memory leaks and code execution when you don’t expect it. This is especially true in angular applications. Here is a popular angular design pattern that calls Completed () when a component is destroyed so that the observable no longer emits values:

import { Subject, Subscription, Observable } from 'rxjs';

ngUnsubscribe = new Subject();

observable
  .pipe(takeUntil(this.ngUnsubscribe))
  .subscribe({ 
    next: (message: string) => {
      this.messages.push(message);
      this.message = this.messages.join(', ');
    }, 
    error: (error: string) => {
      console.log(error);
      this.errMsg = error;
    }, 
    complete: () => console.log('All done.')
  });
  
ngOnDestroy() {
  this.ngUnsubscribe.next();
  this.ngUnsubscribe.complete();
}

The subject is a type of observable, so he can invoke his three methods of diffusion.

Conclusion

In this tutorial, we learned what an Observable is and how to use it to serve asynchronous messages to subscribers within your Angular applications.

You can find a demo of today’s code at stackblitz.com.


Source link

Share.

About Author

Leave A Reply