Angular 12 Tutorial - Reactive Programming

Alongside Vue and React, Angular has currently emerged as one of the most popular and most used JavaScript UI frameworks. Its popularity arises from its capability to provide everything that is expected for other frameworks to provide. 

Unlike the other two, Angular has a unique ideology and architecture because of using Typescript as the primary language instead of JavaScript. One of the significant differences from the other two is the massive use of the decorators, which influence Functional Reactive Programming and the adoption of different patterns.

 In this tutorial, we are going to learn Angular12 Functional Reactive Programming.

Functional Reactive Programming (FRP)

In angular 12, the FRP focuses on the streams and how they can be used in handling both synchronous and synchronous data when building applications in a declarative manner. The FRP provides the management and control of the async data flows.

The FRP  is used mainly through the Observables, which are implemented through the RxJS library. Let's look at the RxJS.

 

Reactive Extension for JavaScript (RxJS) Library

RxJS is a reactive programming library that uses observables to make writing asynchronous or callback-based applications easier.

RxJS implements the Observable type, which is required until the type is included in the language and supported by browsers. In addition, the library includes utility methods for constructing and interacting with observables. These utility functions can be used to do the following:

Observables are created by converting existing code for async activities.

  • Iterating through a stream's values

  • Value mapping to many kinds

  • Stream Filtering

  • Creating multiple streams

 

Observables

Observables serve as functional wrappers for such streams. They give you the ability to subscribe to and unsubscribe from the stream, as well as APIs for transforming the incoming data to your specifications.

How to Create Observables

Every time you create an observable, you need to ensure that its core is the function binding to produce the sourcing values.  You can create the observable from the RxJS. There is a need to access the subscriber inside the function to control the notification flow through the next() method

 

import { Observable } from "rxjs";
const observable$ = new Observable((subscriber) => {
let count = 0;
    const interval = setInterval(() => {
subscriber.next(count);
count++;
}, 1000);
return () => {
clearInterval(interval);
};
});

 

Subscriptions

Now, let’s see how we can subscribe to an observable. Subscribing to an observable is very easy, much easier than you would think.  You only need to pass your observer to your  Subscribe ().  This call will return the subscription object to represent the observable execution and the subscription control. The code snippet below summarizes all

 

import { interval } from "rxjs";
const observable$ = interval(1000);
const subscription = observable$.subscribe((value) => {
console.log(value);
});

 

Error Handling

RxJS includes the catch error operator, which allows you to address known issues in the observable recipe in addition to the error() handler that you specify on subscription. An example of a catch error operation is as follows

import { Observable, of } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { map, catchError } from 'rxjs/operators';
// Return "response" from the API. If an error happens,
// return an empty array.
const apiData = ajax('/api/data').pipe(
    map((res: any) => {
    if (!res.response) {
    throw new Error('Value expected!');
    }
    return res.response;
    }),
    catchError(() => of([]))
);
apiData.subscribe({
next(x: T) { console.log('data: ', x); },
error() { console.log('errors already caught... will not run'); }
});

 

Angular Services and Dependency Injection

Services is a broad phrase that encompasses several variables and operations required by an application to execute properly. A service is often composed of a class with a well-defined purpose, that is, it has a specific task to do and complete it flawlessly.

By differentiating between services and components, Angular promotes reusability and modularity. A component is used to show the view by allowing the user to interact with it. It includes the data binding methods and attributes that serve as a bridge between the application logic and the display.

A component is often developed to execute a specific duty to the services, such as user data validation or data retrieval from the user. The injectable service classes make the processing tasks available to all components.

An Example of a Service

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

 

A service is sometimes dependent on other services. A excellent example is the HeroService, which is reliant on the Logger and Backend services to gain heroes.

 

Example of a Service Depending on another Service

export class HeroService {
  private heroes: Hero[] = [];
  constructor(
    private backend: BackendService,
    private logger: Logger) { }
  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }}

 

The Dependency Injection

In Angular, dependency injection is used to generate new components that include services and any other components that are required. Components require services to function, and injecting a service can allow the component access to a service class.

To define an Angular service, we use the @Injectable() decorator, which generates information that Angular may use to inject the component as a dependency. The @Injectable() decorator denotes a class or component that already has a dependency.

If an Angular detects that a component is dependent on a service, it checks to see if the injector has an existing instance of the service; if not, the injector creates one using the registered provider and adds it to the injector before returning the service

 

Example of a dependency Injection

@Component({
  selector:    'app-hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})