Reactive programming with Angular 2 .In real applications, we have to deal with asynchronous data and the changes of the data that needs to be synchronized between users. The requirements for modern applications sometimes even go further and also provide view updates on the changed data in real time.
Handling asynchronous data and handling real-time data updates, require a major redesign of the data flow in our application. Using observable data structures, we enable our application to master the challenges of asynchronous data where we need to react to change.
Handling data in applications behaves very similarly to streams. You take input, transform it, combine it, merge it, and finally, write it into output. In systems such as this, it’s also very likely that input is in a continuous form and sometimes even of infinite duration. Just take a live feed as an example; this type of data flows continuously, and the data also flows infinitely. Functional and reactive programming are paradigms to help us deal with this kind of data in a cleaner way.
Angular 2 is reactive at its very core and the whole of the change detection and bindings are built using a reactive architecture. The input and output of components, which we’ve learned about in the previous chapter, is nothing but a data flow that is established using a reactive event-driven approach. Angular uses RxJS, a functional and reactive programming library for JavaScript, to implement this data flow. In fact, the EventEmitter
, which we’ve used to send custom events from within our components, is just a wrapper around an RxJS observable.
Reactive and functional programming is exactly what we are looking for to redesign our application in order to handle asynchronous data and data changes. As we already have RxJS at hand from the production dependency of Angular, let’s use it to establish a continuous data flow from our data source into our application. The DataProvider
service that is present in the data-access
folder of our project provides a nice wrapper around our data store using RxJS. As we will use this service in our whole application, we can directly provide it to the bootstrap in the bootstrap.js
file, as follows:
// Import Angular bootstrap function import {bootstrap} from '@angular/platform-browser-dynamic'; import {DataProvider} from '../data-access/data-provider'; // Import our main app component import {App} from './app'; bootstrap(App, [ DataProvider ]);
As a second argument to the bootstrap
function of Angular, we can provide application-level dependencies, which will be available for injection in all components and directives.
Let’s now use the DataProvider
service as an abstraction to obtain data from the PouchDB data store and create a new service responsible to provide project data.
We will create a new ProjectService
class on the lib/project/project-service/project-service.js
path, as follows:
import {Injectable, Inject} from '@angular/core'; import {ReplaySubject} from 'rxjs/Rx'; import {DataProvider} from '../../../data-access/data-provider'; @Injectable() export class ProjectService { constructor(@Inject(DataProvider) dataProvider) { … } }
Looking at the import section of our new module, you can see that we import the necessary dependencies from the Angular core module for dependency injection. Our service class uses the @Injectable
decorator so that we can provide this to the injectors of components. We also inject the DataProvider
service into the constructor of our newly-created service.
The ReplaySubject
class, which we import from the RxJS library, is used to make our service reactive. A subject in the RxJS world is both an observer as well as an observable. It can observe something for changes and then emit further on to all its subscribers. You can think of a subject like a proxy, where it sits in the middle between a source for changes and a group of observers. Whenever the source emits changes, the subject will notify all subscribers about these changes.
Now, the ReplaySubject
class is a special kind of subject that allows you to replay a buffer of changes when new subscribers get added. This is especially useful if you always need to provide some initial data to subscribers. Imagine our data, which we’d like to get propagated into the UI. We want to immediately get the initial data when we subscribe to our service and then going forward, we also want to get notified about changes. Using a ReplySubject
class, which is buffering just one change, suits this use-case perfectly.
Let’s look at the following figure, which illustrates the behavior of ReplaySubject
:
In the preceding figure, you can see that we’re connecting a ReplaySubject
class to a source that is emitting value changes over time. After two emissions, an observer subscribes to our ReplaySubject
class. ReplaySubject
will then replay all buffered changes to the new subscriber as if these events just occurred. In this example, we use a replay buffer length of one. On subsequent value emissions, these will be directly re-emitted to the subscribers of the ReplaySubject
class.
In Next Chapter we will add some logic to the constructor
function in order to emit project data using a ReplaySubject
class.