Saturday, May 23, 2020

Build a Simple .NET Core App on Docker

Sample App Dependencies: ASP.Net Core and Docker Packages

To build an app in Docker, first we need an app to Dockerize. This tutorial uses the ASP.Net Core project from a previous blog post on Adding Login to Your ASP.NET Core MVC App. That blog post shows you how to build a simple .Net Core application that uses Okta for Identity Management. You should work through that blog post, or at very least read it and clone the repo.

You’ll also need:

Build the ASP.NET Core Application

Docker allows you to build an application in pretty much the same way you would create an application to run on your local machine. To get started quickly, clone this git repo:

git clone https://github.com/oktadeveloper/okta-aspnet-mvc-core-sqlite-example.git

Configure Identity Management for Your ASP.NET Core App

First things first, set up an application that will provide us with identity management using the Okta developer console:

  1. Log into The Okta Developer Console
  2. Select Applications from the top menu
  3. Click the Add Application button
  4. Select Web as the platform and click Next
  5. On the Settings page:
    • Name: MyOktaApp
    • Base URIs: https://localhost:5001
    • Login Redirect URIs: https://localhost:5001/authorization-code/callback
  6. Click Done to create the application

Once you’ve created the app, click Edit to change a few settings:

  • Logout redirect URIs: https://localhost:5001/signout-callback-oidc
  • Initiate login URI: https://localhost:5001/authorization-code/callback

At the bottom of the page, you’ll see Client Credentials, including a ClientID and a Client secret. Take note of these for later use.

Update the Settings in the ASP.NET Core App

The sample application you created has identity management configuration stored in appsettings.json, unless you cloned the repo above rather than working through the complete post. In real life, you shouldn’t store this configuration in your source code for security reasons. In this post, we will demonstrate how to reliably pass dynamic configuration to your application, and close this security gap. Start by removing the settings.

Edit appsettings.json to remove:

"Okta": {
    "ClientId": "{OktaClientId}",
    "ClientSecret": "{OktaClientSecret}",
    "Domain": "https://{yourOktaDomain}.okta.com"
},

To test this change:

dotnet run

Should return:

An exception of type 'System.ArgumentNullException' occurred in Okta.AspNet.Abstractions.dll but was not handled in user code: 'Your Okta URL is missing. Okta URLs should look like: https://{yourOktaDomain}. You can copy your domain from the Okta Developer Console.'

Nice work!

Use Docker to Containerize the ASP.NET Core App

Docker is a collection of virtualization technologies wrapped up in an easy to use package. Don’t let “virtualization” trip you up, though. Docker doesn’t deal with virtual machines; instead, it works by sharing a kernel between multiple isolated containers. Each one of these containers operates utterly unaware of other containers that may be sharing the same kernel. Virtual machines, in contrast, run multiple discrete operating systems on top of a virtualized hardware platform that, itself, runs atop the host operating system. Docker is much more lightweight, and many Docker containers can run on a single host machine.

Build the ASP.NET Core App Using Docker

Let’s put Docker to work. The key to Dockerizing an application is the Dockerfile. Add one to the root of your project with the following contents to get started:

FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
WORKDIR /src
COPY ["OktaMvcLogin.csproj", "./"]
RUN dotnet restore "./OktaMvcLogin.csproj"
COPY . .
RUN dotnet build "OktaMvcLogin.csproj" -c Release -o /app

The uppercase words are Docker commands. There aren’t many of them, and you can find the details of them all at Docker’s website.

FROM tells Docker which image you want to use for your container. An image is a compressed file system snapshot. Also, the result of building a Dockerfile is a new image. So, one way to look at a Dockerfile is as a series of transformations that convert one image into another image that includes your application.

  • WORKDIR tells Docker which directory to use for performing subsequent commands.
  • COPY tells Docker to copy a file from your local filesystem into the container image.
  • RUN executes commands within the container image.

So, in plain English - this Dockerfile is based on the dotnet/core/sdk image hosted at mcr.microsoft.com. Docker copies the .csproj file from your local working directory to create your image and dotnet restore restores all the referenced packages. Once that’s done, Docker copies the remaining files from your working directory, then dotnet build creates a Release build at /app.

Manage Dependencies Efficiently with Docker

Reading this, you may be thinking, why bother to copy the project file and run restore before copying the source code and running build? Why not copy everything then build and restore in one step? The answer is caching. Every time a Dockerfile modifies the docker image, Docker creates a snapshot. If you copy a file or run a command to install a package, Docker captures the differences in a new snapshot. Docker then caches and reuses the snapshots if the image hasn’t changed. So, by restoring dependencies as a separate step, the image snapshot can be reused for every build, as long as the dependencies haven’t changed. This process speeds up the build considerably since downloading dependencies can take some time.

Run the ASP.NET Core App in a Docker Container

As mentioned above, a Dockerfile can be considered a series of filesystem transformations. Your current file transforms the Microsoft-provided SDK container into a new container with both the Microsoft SDK and a release build of your application stored at /app.

Try this out::

# Build an image using the Dockerfile in the current directory
docker build --target build -t oktamvclogin .
# Run the image, executing the command 'ls /app'
docker run -it oktamvclogin ls /app

You’ll see that the app folder in your container image contains the Release build output for your project.

Remove ASP.NET Core Development Tools from Your Docker Image

So far, you’ve built your application within a Docker container. Nice work!

However, remember Docker, as a tool, reduces the number of moving parts in your application. To improve reliability by eliminating unnecessary dependencies, we also need to remove development tools, which can cause conflicts and open security risks. The Microsoft-provided SDK image includes development tools, so let’s look at how to get rid of them.

Add the following lines to your Dockerfile:

FROM build AS publish
RUN dotnet publish "OktaMvcLogin.csproj" -c Release -o /app

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base
WORKDIR /app
EXPOSE 5001

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "OktaMvcLogin.dll"]

You will see a few FROM commands, each with an AS clause. This syntax provides multi-stage builds, the key to getting rid of unnecessary dependencies. In plain English, your build process is now:

  1. Use the SDK image to create a release build of the application. Call this stage ‘build’
  2. Use the ‘build’ stage image to publish the application to the ‘app’ folder. Call this stage ‘publish’
  3. Download the Microsoft-provided ASP.NET core image, which has only runtime components. Call this stage ‘base’
  4. Using the ‘base’ stage image, copy the contents of the ‘app’ directory from the ‘publish’ stage. Call this stage ‘final’

So, your Dockerfile now uses the SDK image to build your application, then discards that image and uses a runtime image to run the application.

Run the ASP.NET Core Application in Docker

The ENTRYPOINT command merits special attention. So far you’ve seen how Dockerfiles define a series of filesystem transformations, but more often than not, a Docker container is executable. By that, I mean that you run the container in Docker, and the result is a fully configured, running application. ENTRYPOINT is one of the mechanisms that make that work. When you run a container, Docker executes the command specified by the ENTRYPOINT. In the case of your application, that command is dotnet OktaMVCLogin.dll.

So now…

docker build -t oktamvclogin .
docker run oktamvclogin

… throws the same exception as before:

Unhandled Exception: System.ArgumentNullException: Your Okta URL is missing. Okta URLs should look like: https://{yourOktaDomain}. You can copy your domain from the Okta Developer Console.

Only this time, it’s Dockerized. How’s that for progress?

The application doesn’t work because you removed the sensitive configuration from appsettings.json.

Pass Configuration to Docker

To fix this problem, we need to pass configuration to the Docker container as environment variables. ASP.NET Core picks up all environment variables prefixed with ASPNETCORE_ and converts __ into :. To pass the configuration values for Okta:ClientIdOkta:ClientSecret and Okta:Domain modify your command like this:

docker run -e ASPNETCORE_Okta__ClientId="{yourClientId}" \
-e ASPNETCORE_Okta__ClientSecret="{yourClientSecret}" \
-e ASPNETCORE_Okta__Domain="https://{yourOktaDomain}" \
oktamvclogin

This time the result will be a bit healthier:

Hosting environment: Production
Content root path: /app
Now listening on: 'http://[::]:80'
Application started. Press Ctrl+C to shut down.

NOTE: you may also see a ‘No XML Encryptor’ warning. You can ignore that for this walkthrough.

Configure Docker Networking

From this message, you might think you could go to http://localhost and see your app in all its glory. However, your app runs in a container and listens on port 80 but, by default, your local machine cannot access port 80 on your container. Remember, your container runs in its own little world. That world has its own virtual network, and it’s locked down by default.

Thankfully, you can quickly get access to your container’s virtual network by mapping a port on your local machine to a port on your container.

docker run -e ASPNETCORE_Okta__ClientId="{yourClientId}-" \
-e ASPNETCORE_Okta__ClientSecret="{yourClientSecret}" \
-e ASPNETCORE_Okta__Domain="{yourOktaDomain}" \
-p 5001:80 \
oktamvclogin

Now, if you open a browser and go to http://localhost:5001 (because you mapped port 5001 to port 80 in your container), Et voila!

NOTE: this approach is suitable for development. However, for production workloads, Docker offers a comprehensive set of options designed for managing virtual networks. For more information see the networking overview in Docker’s documentation.

Configure SSL/TLS for Your Docker Image

If you click on the Login link in your application, chances are you’ll get an error from Okta with a message:

Description: The 'redirect_uri' parameter must be an absolute URI that is whitelisted in the client app settings.

This problem happens because when you configured the application in the Okta dashboard, you specified that the redirect URL was HTTPS. Now, since you accessed the site using HTTP, the redirect URL doesn’t match, and you get this error. One solution is to update the redirect URL in the Okta application. While that will work, it’s a bad idea. The redirect contains sensitive information and to prevent it from being read while in transit, it should be protected using a TLS channel.

Create a self-signed certificate

To set up TLS, you’ll need a certificate. In real life, you’d buy one from a reputable provider, but for this walkthrough, a self-signed certificate will do the job.

Generate a certificate:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

To use the certificate with Kestrel (the ASP.NET Core webserver), we need to create a pfx file that has both the public and private keys. You can do that using:

openssl pkcs12 -export -out webserver.pfx -inkey key.pem -in cert.pem

As part of the certificate creation process, you’ll be prompted to create an Export password. Be sure to take note of this as you’ll need it later to use the certificate. You’ll also be walked through the configuration process (Country NameState or Province, etc.).

Add the certificate to the Docker image

You’ve created a certificate in your local filesystem. To use it in your Docker container, modify the Dockerfile to copy it into the final image.

Change the `final’ stage to:

FROM base AS final
ENV ASPNETCORE_URLS="https://+"
ENV ASPNETCORE_Kestrel__Certificates__Default__Path="./webserver.pfx"

WORKDIR /app
COPY --from=publish /app .
COPY webserver.pfx .
ENTRYPOINT ["dotnet", "OktaMvcLogin.dll"]

Setting the ASPNETCORE_URLS environment variable to https://+ ensures that the webserver only listens for https requests.

Since you’ve changed the Dockerfile, you can rebuild the image and run it:

docker build -t oktamvclogin .
docker run -e ASPNETCORE_Okta__ClientId="{yourClientId}" \
-e ASPNETCORE_Okta__ClientSecret="{yourClientSecret}" \
-e ASPNETCORE_Okta__Domain="{yourOktaDomain}" \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="{yourExportPassword}" \
-p 5001:443 \
oktamvclogin

Notice the additional environment variable with the certificate export password and also, that the port mapping has changed from port 80 to port 443.

You can now navigate to https://localhost:5001, and this time, you’ll be able to log in and use the sample application correctly.

NOTE: Since you’re using a self-signed certificate, your browser may display a warning page. You can safely ignore this warning.

Not the Best Way to Start Your Docker Container

Converting an application to run in Docker is relatively straightforward and offers significant benefits. However, passing a whole load of configuration to docker run isn’t particularly user-friendly and is error-prone. Thankfully, the good folks at Docker have already come up with a solution to this problem - docker-compose.

Using Docker Compose is pretty straightforward. Create a file named docker-compose.yml in the same folder as your Dockerfile and source code and add the following:

version: "3"
services:
  web:
    build: .
    image: oktamvclogin
    ports:
      - "5001:443"
    environment:
      - ASPNETCORE_Okta__ClientId: "{yourClientId}"
      - ASPNETCORE_Okta__ClientSecret: "{yourClientSecret}"
      - ASPNETCORE_Okta__Domain: "{yourOktaDomain}"
      - ASPNETCORE_Kestrel__Certificates__Default__Password: "{yourExportPassword}"

The docker-compose file contains all values you previously passed to the docker run command.

Now, to run the application:

docker-compose up

And it all just works. Happy days.

Of course, this is barely scratching the surface of what you can do with Docker Compose. To find out more, check out the official overview of Docker Compose

Containerize and configure an ASP.NET Core app with Docker

By working through this post, you’ve learned how to:

  • Containerize an ASP.NET Core application with Docker
  • Pass configuration to a Docker container
  • Configure SSL/TLS for a containerized ASP.NET Core application
  • Use docker-compose to efficiently run a Docker container with a particular configuration

Now, by including a Dockerfile along with your source code, any developer can build your app – reliably. They can build it in any environment, as long as they have Docker installed, and it will work in precisely the same way. Every time, without exception. No dependency issues, no operating system hassles. It will just work. Not only that, but you can deploy the same container directly to production without any further modification.

How Functional Reactive Programming (FRP) is Changing the Face of Web Development


Like when watching a sleight-of-hand magician, Web developers have been distracted by the recent popularity wars between the various front-end frameworks, and we’ve missed a fundamental shift in the nature of these frameworks. Functional Reactive Programming (FRP) has been quietly and steadily showing up in many aspects of the main frameworks of today.


You see this same change happening elsewhere, but as frameworks are the center of the front-end Web world, this is where all these influences come together. Why is this? Before I can answer that, you need to understand a few things about FRP.
What is FRP?

The simple answer to this question is that there is no simple answer. To the more academic side of the industry, FRP is all about values that change over time, sometimes called signals. But to the rest of the industry, FRP is more of an umbrella term that refers less to this esoteric definition, and more to the ancillary constructs and ideas that are generally part of FRP. These ideas and technologies include:
Immutable data
Observables
Pure functions
Static typing
One-way state transitions

Let’s take a quick look at each one of these items.
Immutable Data

Immutable data is a data type that can’t change any value once it is created. Imagine an array that’s created with two integers, 2 and 5. After you create it, you can’t remove or add any elements, or change the values of either of those two elements. At first, this may seem to be unnecessarily limiting. When you need to turn that array into an array with three elements, 2, 5, and 8, you create a new array with those three elements. This may sound extremely non-performant, but in practice, it’s not nearly as expensive as you would think and when used in change detection algorithms that exist in just about every front-end framework, it can lead to amazing performance gains. The most popular library that implements this is immutable.js.

Here’s a simple example of using immutable.js to create a data structure, and then make a modification.
var map1 = Immutable.Map({a:1, b:2, c:3});
var map2 = map1.set('b', 50);
map1.get('b'); // 2
map2.get('b'); // 50




Notice that in the preceding code example, a new object is created when you change just one value. First, a map is created and then one of the values in that map is changed to a new value. This creates an entirely new object. The old object, map1, still has 2 for the value of b, and map2 has 50 for the value of b.
Observables

Observables have existed in the JavaScript world for a long time, although the FRP version of observables usually comes with more than the simplest form of an observable. These observables often have many more features than a typical observable and you can see this in action with libraries such as RxJS and Bacon.js. Like immutable data, observables give significant performance gains in change detection strategies.

Here’s an example from the RxJS library that shows how to subscribe to an async data source, filter and map it, and then print out the results as they become available. This works not only with one piece of return data, but with a stream of data arriving intermittently as stock data does.
var source = getAsyncStockData();
var subscription = source
.filter(function (quote) {
return quote.price > 30;
})
.map(function (quote) {
return quote.price;
})
function (price) {
.subscribe(
console.log('Prices higher than $30: $' + price);
},
function (err) {
console.log('Something went wrong');
});
subscription.dispose();



Pure Functions

Pure functions are perhaps the most vague of these items because "pure" is a very common word. In this case, a pure function has no side effects. You can run the function as many times as you want and the only effect is that it computes its return value. Pure functions are significantly easier to both test and maintain. Using them lowers maintenance costs in applications written in frameworks like React and Mithril.

Here’s a classic example of a non-pure function with side effects:
function getCustomerPrice(customer, item) {
var price;
if(customer.isUnapproved) {
customer.unapprovedAttempts
.push({itemId: item.id})
} else if(customer.isPreferred) {
price = price * .9;
}
return price;
}




Notice how the Customer element is modified if they’re unapproved? This is an example of a side effect. It’s like a byproduct of the main job of the function, which is to simply get the customer price, and is the source of many bugs in programming. That’s why you want pure functions with no side effects. A pure function version of this same code would leave logging the unapproved attempt to another piece of the program and simply return the customer price, as in the following:
function getCustomerPrice(customer, item) {
var price;
if(!customer.isUnapproved &&
customer.isPreferred) {
price = price * .9;
}
return price;
}




In any realistic application, you’ll need state, and you’ll need to modify that state at certain points, like logging the unapproved attempt shown in the first example here. But by drawing a line between areas that modify state, which are non-pure, and the parts that don’t, which are implemented with pure functions, you create a lot of code that’s simpler to build, test, and maintain. Pure functions rely on their inputs and not on any context. That means that they can be moved around and refactored easily. And, as shown in this example, pure functions tend to help you follow the single responsibility principle and keep things simple.
Static Typing

Static typing is the system whereby types of variables are established at compile time. This allows a program to avoid a host of typical run time errors and simple bugs. Many statically typed languages require a fair amount of ceremony to document the types and many programmers find this onerous. Some statically typed languages can infer types based on context, which means that most types don’t need to be declared. You see this in Flow and TypeScript.

Let’s look at an example of using an instance of a class in vanilla JavaScript, and again with TypeScript
class TodoModel{
// class properties

complete() {
// implementation
}
}
// vanilla JS
var todoModel1 = new TodoModel();
todoModel1.finish(); // throws a runtime error
//TypeScript
var todoModel2:TodoModel = new TodoModel();
todoModel2.finish(); // compile time error




The only difference between these two is that you’ve told the compiler that todoModel2 is of type TodoModel, which is a class that you declared. This lets the compiler know that if, later on, someone tries to call the finish method as shown in the snippet, there’s no finish method and the error can be thrown at compile time. This makes the bug much cheaper to fix than waiting until unit tests are written, or even worse, having the error thrown at run time.

Also, notice that an inferred type system can give the same benefits by inferring that the type is TodoModel. That means that you don’t have to declare the type, and the "vanilla JS" version can still act as if typed. Errors like the one discussed can still be caught at compile time. Both Flow and TypeScript support this.
Advertisement

One-Way State Transitions

One-way state transitions are perhaps the most significant of these various technologies. One-way state transitions are an architecture whereby changes to the model all go through a common type of dispatcher, then, when changes to the model are made, these changes are rendered to the screen. Figure 1 illustrates this idea. This is a way of thinking about your program as a simple cycle. Your model passes through a rendering function and becomes viewable elements. Changes (usually represented by user events) update the model, which then triggers a re-rendering of the view. The rendering functionality is ideally implemented as a pure function.
Figure 1: One-Way State Transitions.

This concept deserves its own article to sufficiently explain these ideas, so I’ll just touch on it. This architecture is significantly simpler and easier to learn than typical development because all actions that can change the state of a program are clearly and centrally defined. This makes it easier to look at a program and understand how it behaves. Imagine learning to operate a car without having first spent years in one, and having no guidance. As you explored it, you’d discover that you could lock and unlock the doors, open the hood and if you sat in it, you could turn the steering wheel (which doesn’t seem to do anything useful), but that doesn’t get you anywhere near to driving. You still need to learn that the key goes in the column to start the car, and how the radio and air conditioning work, and how turning the wheel really only matters when you’re in motion, and how the pedals control the movement of the vehicle.

Now instead, imagine a manual that listed every action the car could take, and sent you to a page where you could read exactly what effect that action had. This is the difference between common programming architectures and one-way state transitions.

Using this methodology, it’s cheaper to bring new developers onto a project because they can come up to speed quicker, with less direction, maintenance costs are down because problems are easier to track down, and brittleness is reduced overall. The largest payoff may be that as project sizes grow, velocity doesn’t suffer the typical slow-down. Although the functional programming crowd (Haskell and Erlang programmers, among others) have been touting these very benefits for a long time, mainstream development as a whole hasn’t been listening until now. And many people don’t even realize where all of these ideas came from.
Deja Vu

It’s important to note that most of these ideas are not particularly new, and many of them existed as early as the 80s or even earlier. Each of them can bring benefits to most development projects, but when used together, the total is greater than the sum of its parts. What’s particularly interesting is the fact that these ideas aren’t just suitable for a subset of application types. These same ideas have been used in games, animation, operating systems, and everything in between. For an interesting read on the parallels between React and Windows 1.0, check out this article: http://bitquabit.com/post/the-more-things-change/.
FRP Becomes Mainstream at Last

We are starting to see each of these previously mentioned ideas making their way into the mainstream of the Web development world. This is best recognized by their effect on the two dominant frameworks, React and Angular 2. Although it hasn’t been released yet, due to the dominant market share of Angular 1, Angular 2 is definitely one of the frameworks occupying the attention of most front-end developers.

I’d be remiss if I didn’t mention a third framework that you’ve probably never heard of: Elm. Elm is another front-end framework that makes the audacious move of being written in an entirely new language. Built by Evan Czaplicki while he attended Harvard, it’s an attempt to make FRP more digestible to mainstream programmers. The reason that this is so remarkable is that it’s had a heavy influence on both React and Angular 2.

The main reason that we’re seeing these influences make their way into Web development now is centered on the never-ending quest for more maintainable code. Evan Czaplicki gave a great talk on this topic titled "Let’s be Mainstream" ( HYPERLINK "https://www.youtube.com/watch?v=oYk8CKH7OhE" https://www.youtube.com/watch?v=oYk8CKH7OhE). As front-end applications grow ever larger, the need to make them easier to maintain has become more important. Because of this, we’re seeing new techniques being introduced in an attempt to achieve this goal.

You can see this if you take a brief look at the overall history of front-end Web development. At each stage, the need for maintenance has driven a continual quest for methods to manage the complexity. The first attempt was simpler APIs through libraries like jQuery. Then frameworks came on the scene as a way to organize code into whole applications while still being modular and separating out various concerns. Automated testing quickly became a hot topic at this point. Then, increasingly fully featured frameworks appeared to help developers build bigger and bigger apps. All the while, everyone tried new methods to deal with constantly-expanding code bases.

Another reason we’re seeing these influences now is that the high demand in front-end Web development continues to attract developers from other areas. These developers are bringing with them ideas that worked for them in other environments, and existing developers are looking to other areas for ideas that can help improve code built for the browser.

Changes are popping up all over. Both React and Angular 2 support using observable and immutable data. Both of them use one-way state transitions internally, and React even goes so far as to codify it for developers to follow with libraries such as Flux and the more recent Redux. Redux was directly inspired by Elm. Angular 2 supports using Redux or something similar, although they don’t directly encourage it at this point. Both of them, meanwhile, encourage developers to use static typing with both Flow for React, and TypeScript in the Angular world.
What’s Next

It’s difficult to predict the future in any reasonable way, but there are a few places that you might see these ideas in action.

As FRP becomes mainstream, that could open up the door to widespread adoption of FRP languages like Elm. Combined with the features of Web Assembly, which makes JavaScript a more viable compile target, FRP languages such as Elm or Haskell—or new ones we haven’t seen yet—could possibly make their way into popular Web development.
Advertisement


Another thing we’ll likely see is a near-standardization on architectures using Flux-like one-way data state transitions. The React world seems to be standardizing on Redux, a simpler implementation than Flux, and adaptations of Redux for other frameworks are starting to appear.

Obviously, reading an article is useless unless it gives you actionable knowledge. So here’s my advice to take advantage of the winds of change that are blowing in our industry:
Be Aware. Just knowing what’s going on will put you ahead of the curve.
Learn. Go check out RxJs or Immutable.js or learn React and Angular 2.
Open your mind. Even if these ideas sound strange to you, don’t resist change. Open yourself up to new ideas and new paradigms. This is perhaps the best piece of advice I can give you
.

Saturday, May 9, 2020

RxJS a deep dive with Angular 8


What and Why RxJS?

Reactive programming was first implemented by Microsoft engineer Eric Meijer while working in C#, LINQ. LINQ in the .NET framework provides the first kind of reactive experience to developers. Later in 2012, it was open-sourced and now used by all big companies including github, Netflix, etc.

RxJS implements reactive extension for TypeScript and JavaScript. ReactiveX is a combination of the observer pattern, iterator pattern, and functional programming. check reactive.io for more details.

Below attached image to view RxJS world!

  • Observable pattern: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. In Angular, there are many scenarios where we have to deal with events, streams of events.
  • Iterator Pattern: Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
  • Functional Programming: Functional programming is a programming paradigm where we use a pure function, avoiding the shared state, and mutable data. Currying in JavaScript is one of the great examples of functional programming.

RxJS is an event-based and asynchronous program that uses the observable sequence. Observables can be subscribed by a method, changed by a set of methods, and can return an asynchronous set of streams which further changed by a set of methods.

You can see the word subscribe here, wait it looks like you are talking something like Promises?

Observing Universe depends upon time and space

Observable vs Promise:

In general, promises handle single events that fail or succeed. Though now there are many libraries which can make the promise more powerful.

Observable is a set of the stream that can handle no to many events. Observables are preferred over promises because they can be aborted, retry in case if it fails, and much more!

Example:

In the below code, we are creating one service ObservableDemoService which is implementing HttpClient. This service getting initial page info to load data. Method getinfo$ getting array stream of DemoInterface[] and in pipe handling error. In the component constructor injecting dependency of ObservableDemoService. Also creating an error subject errorMessageSubject to hold or show error in view. Now calling getinfo$ method of ObservableDemoService with pipe. Pipe takes a bunch of other methods. Pipe is very useful when we are performing some data messaging on the response, here we are initializing the data grid component.

Here we are creating promiseinAction which returns a resolve and reject promise when supplied true and false respectively. We are implementing ngOnInit method to call getPromise(true || false) method. We can see clearly here we have only two response success or failure.

Good News! Promises can be converted to Observables:

The good part is a promise can be converted to Observables when required!

RxJS operators that accept Observables can also accept a promise as well. You just need to change promise to observable. The best part is you don’t need to change all the code in the Angular app!

OR


Observable vs Subject

Subject is a special type of Observable. Observable is one of the base classes in RxJS and Subject is one of its derived types. Subjects implement observer design pattern which is required to set some value i.e. this.Subject.next(message). Observable always need a subscription and implement the observable pattern. Observable is always unidirectional meaning it flows from source to subscriber. Subject is bidirectional, information flow from the source to subscriber, and vice versa.

Types of Subject:

  1. BehaviourSubject: A BehaviourSubject stores the latest value and immediately sends it to all subscribers. i.e. I have created a message service that can be consumed from two Angular components and its bidirectional.

Component1:

Component2:

2. ReplaySubject: A replay subject stores n number of values and immediately send it to the subscriber. i.e. in the above data service if we change messageSource as ReplaySubject and pass 3 then it will cache the last three values on subscription.

3. AsyncSubject: Async subject waits until it completely and then sends the final value to the subscriber. The keyword here is the final value. If we add two values in the below example “Hello 1” and “Hello Again”, When we do asyncsub.complete() then only last value will be printed. The last value is the final value in our case.

4. ConnectableObservable: A wrapper that transforms observable behave like a Subject. It provides a .connect() method to transform. Very less likely you will be using it in Angular application.

observable.connect();


Managing Stream Greater Power !!

RxJS operators provide managing streams, combining the stream into a single stream. It also helps in calling APIs (set of observables) sequential and parallel. But the main problem is there are so many operators. Combining operators is always a challenge. RxJs provides a set of the wizard on their website for combining these operators. If the wrong operator is combined it will lead to race conditions. Also, all the subscriptions need to unsubscribe when components are out of scope, failing this will led to memory leaks. Memory leaks are really really scary especially when the application is running in production environments.

Combining Observables into one Stream:

  • mergeMap: Creates new observables for any given source. All previous streams/observable keep alive. There is no order in the returned observables, moreover, the order is not preserved. The best use case for mergeMap is when combining a click event with API calls.
  • concatMap: Similar to mergeMap but the order of observables is well preserved. Preserve the order and emits all observable value, works synchronously. Execute slowly because it works synchronously, waits for first observable to complete then only start new observables stream. The best use case is when you are calling an API which gives you id and that id is used in another API.
  • switchMap: Immediately creates new observables and completes the old observables. The best use case for switchMap is search auto-complete. Whenever the user starts typing a new keyword for search, a new observable is created and the old one is completed. Check combineLatest example below with mergeMap and switchMap.
  • flatMap: Immediately creates observables and previous observables are kept alive. fatmap is an alias of mergemap, mergeMap accepts an optional parameter concurrency, which defines how many Observables can be subscribed at the same time.
  • exhaustMap: Creates observable and waits for it until it complete. All other observable is ignored while waiting for the observable to complete. Best use case is to use login in the Angular app. Once the user clicks on login then wait until authentication is done! exhaustMap is just the opposite of switchMap. switchMap immediately creates a new observable and completes the old ones however exhaustMap first complete the initial observable and ignores the new ones.

Joining Observables into Array:

  • forkJoin: Calls all observable parallel. Returns all observables as an array once all call is completed. The best use case is when you want to call APIs that are not depends on each other. Multiple uploads are one of the scenarios where we can use forkJoin. Also, we can combine insert and update APIs in forkJoin based on conditions.
  • combineLatest: Begins when all observables fired at least once. Afterwards it fires when any of the event changes.

The best use case in an Angular application is combining a data table and dropdown events action. Dropdown represents the product with category and category ids and once selected we have to show product details based on category id. Now check the below code:

Once merged with combined with the latest whenever the user selects a product category dropdown data table data automatically filtered. No need to write any event in Angular component. This is sometimes called a reactive style of development.

Now we can use mergeMap while filtering the selectedCategory. If the user is clicks on the drop-down again and the previous request is not completed, then switchMap will cancel the previous request and start a new Observables.


With great power comes great responsibility! Memory Leaks are real!

I know you already heard this phase. But in the RxJS world, it’s very important to always unsubscribe to open observables and subjects. In Angular, implement ngOnDestroy and unsubscribe.

However many times it is difficult to remember which teardown method to unsubscribe.

How about if the subscription is automatically unsubscribed rather than doing it manually?

It is possible in frameworks like Angular if we are using async pipes. Async pipes automatically unsubscribe open observables and subject once a component is out of scope. Now we already created products$ in the above example which holds the product list coming from getting service. Using product$ | async pipe we can show the product details. Below is the view code snippet.

Level Up Coding

Coding tutorials and news.

Free hosting web sites and features -2024

  Interesting  summary about hosting and their offers. I still host my web site https://talash.azurewebsites.net with zero cost on Azure as ...