Dependency Injection and Observables in Angular A practical explanation and some implementation samples of two key Angular concepts: Dependency Injection and Observables

Dependency Injection and Observables in Angular

If we're used to work with modern languages such as .NET Core, ReactJS, AngularJS, or Angular, we most likely already know what Dependency Injection (DI from now on) is and the huge amount of benefits it brings in terms of code reusability, testability, readability, simplicity, and so on. In the unlikely case you don't, we'll make fun of ourselves trying to shrink one of the most important code design patterns of the latest 20 years in less than 20 words; it's a coding technique where a class receives its dependencies from external sources rather than directly instantiating them.

Those who want to know more about it can take an extensive look at this great guide from the official Angular documentation, which explains how DI works both in general terms and within the Angular framework:

https://angular.io/guide/dependency-injection

A sample Angular Component

Let's take a look at how DI can be implemented within a standard Angular component class:

Here's a breakdown of what it actually does:

  • In lines 1-2, we import the Angular references that we need from the @angular/core and @angular/common/http packages; since we’re creating a Component, we need the Component base class. Other than that, we also need to import the  Inject  decorator, which we're using within the class constructor to make the baseUrl parameter available through Dependency Injection (DI), and the HttpClient class to perform HTTP requests, also being instantiated using DI.
  • In lines 4-8, we set up the component UI layout and settings:
    • The selector, which gives a name to the HTML pseudo-element we'll have to use to include the component within another component's template; in this case, with the given value, it will be <quiz-list></quiz-list>
    • The templateUrl, pointing to a single HTML file containing the component template
    • The styleUrls, pointing to the CSS files that will contain the component styles; the expected value is an array, meaning that we can split the component styling into multiple CSS files
  • Starting from line 10, we can find the QuizListComponent class declaration, along with all its properties, constructor, and methods.

We can see that the above class is using the HttpClient class to call two consecutive methods: .get<Quiz[]>() and .subscribe(). The former, as the name suggests, issues a standard HTTP request to a MVC Controller to fetch an array of JSON elements - arguably represeting the quizzes; we use a local string variable to assemble the controller's endpoint URL and then toss it as a parameter. The latter instantiates an Observable object that will execute two very different actions right after a result and/or in case of an error. Needless to say, all this will be done asynchronously, meaning that it will run in a separate thread (or scheduled for later execution), while the rest of the code continues to execute.

Before going further, it can be useful to explain what an Observable actually is.

The role of Observables

Observables are a powerful feature for managing async data; they are the backbone of the ReactiveX JavaSript Library (RxJS), which is one of the Angular required dependencies, and are planned to be included in the final release of EcmaScript 7. If you're familiar with ES6 Promises, you can think of them as an improved version of them, with some important changes in how they actually work.

One of the most relevant differences with the previous approach is that Observables have a lazy behavior by design, meaning that they won't fire unless there is a valid subscription issued by a .subscribe() function call. This is a major perspective switch from the AngularJS Promises, that will execute right off the bat, regardless of how the client code will use their result afterward.

Another important difference involves the .subscribe() function, which will be fired upon completion of the add task of ItemService. In Angular, subscriptions are designed to work just like a standard .then() or .complete() function featured in most async-based JavaScript libraries (AngularJS/Promises, JQuery/AJAX, and so on), with the key difference that they
are also bound to the Observable itself; this means that they won't just trigger once and resolve, but they will be executed each and every time the Observable completes its task(s)
until it ceases to exist, unless they get cancelled by calling the .unsubscribe() function method on their Observable.

That said, we can easily note that the minimalistic HTTP requests we've been implementing are hardly a good example to demonstrate the advantages of this behavior as most of these
Observables will fire only once; to better see the difference with the previous approaches, we will have to implement some truly reactive functionalities such as Search with Autocomplete, Websockets, Push Notifications, Instant Messaging, and similar stuff.

Angular makes an extensive use of both Observables when dealing with data. Those who want to get additional information can take a look at the following URL, taken from the RxJS official documentation:

http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

This article is part of the ASP.NET Core 2 and Angular 5 book, available as paperback, e-book and as a 26-lessons video-course. Promo Code: ASPCA50 to get it with a 50% discount! The book's latest edition, updated to ASP.NET Core 5 and Angular 11, is available here.

About Ryan

IT Project Manager, Web Interface Architect and Lead Developer for many high-traffic web sites & services hosted in Italy and Europe. Since 2010 it's also a lead designer for many App and games for Android, iOS and Windows Phone mobile devices for a number of italian companies. Microsoft MVP for Development Technologies since 2018.

View all posts by Ryan

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.