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 ] }) |