I recently was helping another developer understand the difference between Subject, ReplaySubject, and BehaviourSubject. And thought that the following examples explain the differences perfectly.

Subject

A subject is like a turbocharged observable. It can almost be thought of an event message pump in that everytime a value is emitted, all subscribers receive the same value. The same analogy can be used when thinking about “late subscribers”. A Subject does not have a memory, therefore when a subscriber joins, it only receives the messages from that point on (It doesn’t get backdated values).

So as an example :

let mySubject = new Subject<number>();

mySubject.subscribe(x => console.log("First Subscription : " + x));

mySubject.next(1);
mySubject.next(2);
mySubject.next(3);

mySubject.subscribe(x => console.log("Second Subscription : " + x));

mySubject.next(4);

This will output :

First Subscription : 1
First Subscription : 2
First Subscription : 3
First Subscription : 4
Second Subscription : 4

Pretty straight forward. The first 3 values were output from the subject before the second subscription, so it doesn’t get those, it only gets new values going forward. Whereas the first subscription, as it subscribed before the first values were output, gets everything.

Now for the most part, you’ll end up using Subjects for the majority of your work. But there can be issues when you have async code that you can’t be sure that all subscriptions have been added before a value is emitted. For example :

let mySubject = new Subject<number>();
myAsyncMethod(mySubject);
mySubject.subscribe(x => console.log("First Subscription : " + x));

Imagine that “myAsyncMethod” is an asynchronous method that calls an API and emits a value on the given subject. This method may or may not complete before the subscription is added and therefore in rare cases, the subject did output a value, but you weren’t subscribed in time. These sort of race conditions on subscribing is a big cause of headaches when using plain Subjects.

ReplaySubject

That’s where ReplaySubject comes in. Imagine the same code, but using a ReplaySubject :

let mySubject = new ReplaySubject<number>();

mySubject.subscribe(x => console.log("First Subscription : " + x));

mySubject.next(1);
mySubject.next(2);
mySubject.next(3);

mySubject.subscribe(x => console.log("Second Subscription : " + x));

mySubject.next(4);

This outputs :

First Subscription : 1
First Subscription : 2
First Subscription : 3
Second Subscription : 1
Second Subscription : 2
Second Subscription : 3
First Subscription : 4
Second Subscription : 4

Notice how we get the first 3 values output on the first subscription. Then immediately as the Second Subscription joins, it also outputs the first 3 values, even though when they were emitted, the second subscriber had not yet joined the party. Then going forward, both subscribers emit the 4th value.

So what’s going on here? It’s actually quite simple. A ReplaySubject remembers the previous X values output, and on any new subscription, immediately “replays” those values to the new subscription so they can catch up. I say previous “X” values because by default, a ReplaySubject will remember *all* previous values, but you can configure this to only remember so far back.

For example :

let mySubject = new ReplaySubject(2);

This will remember only the last 2 values, and replay these to any new subscribers. This can be an important performance impact as replaying a large amount of values could cause any new subscriptions to really lag the system (Not to mention constantly holding those values in memory).

Back to our problem async code with Subject. If we change it to a ReplaySubject :

let mySubject = new ReplaySubject<number>();
myAsyncMethod(mySubject);
mySubject.subscribe(x => console.log("First Subscription : " + x));

Then it actually doesn’t matter if myAsyncMethod finishes before the subscription is added as the value will always be replayed to the subscription. Pretty nifty!

BehaviorSubject

A BehaviorSubject can sometimes be thought of a type of ReplaySubject, but with additional functionality (Or limitations depending on how you look at it).

If you think of a BehaviorSubject as simply being a ReplaySubject with a buffersize of 1 (That is, they will only replay the last value), then you’re half way there to understanding BehaviorSubjects. The one large caveat is that BehaviourSubjects *require* an initial value to be emitted.

For example :

let mySubject = new BehaviorSubject<number>(1);

mySubject.subscribe(x => console.log("First Subscription : " + x));

mySubject.next(2);
mySubject.next(3);

mySubject.subscribe(x => console.log("Second Subscription : " + x));

mySubject.next(4);

This outputs :

First Subscription : 1
First Subscription : 2
First Subscription : 3
Second Subscription : 3
First Subscription : 4
Second Subscription : 4

So again, we have the ReplaySubject type functionality that when the second subscriber joins, it immediately outputs the last value of 3. But we also have to specify an initial value of 1 when creating the BehaviorSubject.

But why is an initial value important? Because you can also do things like so :

let mySubject = new BehaviorSubject<number>(1);
console.log(mySubject.value);

Notice we can just call mySubject.value and get the current value as a synchronize action. For this to work, we always need a value available, hence why an initial value is required. Again, if you don’t think that you can provide an initial output value, then you should use a ReplaySubject with a buffer size of 1 instead.

Also, just a quick warning on BehaviorSubjects, this might be one of those times where spelling trips you up if you are not American. For example if you are getting the warning :

Cannot find name 'BehaviourSubject'

Just remember it’s Behavior not Behaviour!

In a recent project, I’ve gotten into the habit of using the timer operator inside RxJS. At first I thought it was quite hacky, but actually.. It can come in incredible useful in scenarios that you may have previously used setTimeout. That might make it sound even worse! But let me explain.

In my particular case, I needed to load an Esri map on the page. If you’ve never heard of that before, just think of it as a Google Maps style widget. However, loading this widget could max out bandwidth on some connections as it tried to load many tiles (Images of the map) all at once. Because of the async nature of my application, I was also trying to load some important information to display side by side with the map. This information was far more important than loading the map fast, and yet, they were competing with each other for resources.

What I really wanted was just a small delay in loading the map to give a chance for other requests to go through first. This was somewhat hacky but actually worked well. My first iteration was simple with a timeout like so :

let mapLoader = setTimeout(() => this.loadMap(), 130);

//Somewhere in my ngDestroy
clearTimeout(mapLoader);

This worked actually just fine. But my main issue is that I’ve introduced a new paradigm for “unsubscribing” from observables, in this case we use the clearTimeout method to remove timeouts. What I wanted was a way to use RxJS, so that when I unsubscribe from all my other subscriptions, this simple timer is also unsubscribed.

And easy enough, RxJS has just the thing! Timer.

We can change our code to look like so :

import { timer } from 'rxjs';

let mapLoader = timer(130).subscribe(x => this.loadMap());

Simple! All this does is set a timer to go off in 130ms. Best of all, it returns a subscription just like any other Observable.

If we wanted to, we could also do something like so :

import { timer } from 'rxjs';

let mapLoader = timer(130, 130).subscribe(x => this.loadMap());

So run our loadMap() method in 130ms, and then run it again *every* 130ms after that. These numbers can be completely different, for example :

import { timer } from 'rxjs';

let mapLoader = timer(0, 130).subscribe(x => this.loadMap());

Run right now, and *then* run every 130ms etc.

While Timer might not be used in every project, it can come in incredibly handy as either a delay, or a much nicer way to have repeating timers without having to use recursive setTimeouts. And best of all, they fit with the existing paradigm of Observables/Subscriptions within Angular.

The use of TrackBy in my opinion is severely underrated in Angular. The performance benefits gained from using it can be huge (And very noticeable) for such a small code change. But before we dive too deep, let’s talk about how an NgFor loop works in Angular when you don’t use TrackBy at all.

Imagine a simple component with the following code behind :

export class AppComponent {
  employees : any[];

  resetEmployees() {
    this.employees = [
      {id : 1, name : 'John Smith'}, 
      {id : 2, name : 'Jane Smith'}, 
      {id : 3, name : 'Joe Bloggs'}, 
      {id : 4, name : 'Janey Blogs'}, 
      {id : 5, name : 'John Doe'}, 
      {id : 6, name : 'Jane Doe'}, 
    ];
  }
}

And a view that is also rather simple like so :

<button (click)="resetEmployees()">Reset</button>
<table>
  <tr *ngFor="let employee of employees">
    <td [attr.data-id]="employee.id">{{employee.name}}</td>
  </tr>
</table>

Now imagine a scenario like so :

  1. The page is loaded, no employees have been loaded, so the list is empty.
  2. We hit the reset button, and employees are set, and so the ngFor loop kicks off and draws them.
  3. We hit the reset button *again*. Employees are set, but it’s the same list! Doesn’t matter, ngFor loop kicks off and we re-draw them

It’s step 3 that is a problem. It’s an issue because drawing in the Dom is actually an expensive operation. Setting the list (even to the same list), means we remove all 6 items from the list, and then draw 6 items again.

So why?

The reason is that ngFor actually has a “default” trackBy. And it’s by object reference. Each time we set the list, because the actual reference has changed (Even the though the values have not), we redraw the entire table Dom again.

You can actually test this by viewing the elements in chrome dev tools. Each time you click reset, you’ll see the table light up like a xmas tree because it’s having to redraw everything.

Adding TrackBy

The first thing we need to do to add a TrackBy is to first identify a unique field on our array items. It actually doesn’t have to be a single field, but it should be some way to uniquely identify each record. In our case that’s easy, we can use the id field which is unique among all employees.

We then add a method that will take an item, and return the unique identifier.

getEmployeeId(index : number, employee : any) {
  return employee.id;
}

Then on our ngFor loop, we add the trackBy like so :

<table>
  <tr *ngFor="let employee of employees;trackBy:getEmployeeId">
    <td [attr.data-id]="employee.id">{{employee.name}}</td>
  </tr>
</table>

Note we don’t *call* getEmployeeId, we just pass the name of the method that we want to run to identify unique rows. Now when we run the reset method, and we watch it in Chrome Tools, we can see it no longer lights up as it’s not having to re-draw everything time and time again.

Where Is This Useful?

So the main question probably becomes, but where is this useful? You might think at first that you never do this sort of wholesale array setting. But in reality, you probably do. Imagine this code :

this.employeeService.getAll().subscribe(x => {
  this.employees = x;
});

It’s extremely common for API calls (Or really any rxJS subscription), to completely reset the value of an array with the results. If we didn’t use trackBy, and this ran often, we would end up redrawing a lot of elements that even if at first with a small number of results we didn’t notice, could quickly turn into a complete performance sink.

Other Notes On TrackBy

Trackby doesn’t suddenly make your code unresponsive. I’ve seen this crop up a little bit where people think if an item is set with the same id, then nothing about that item will update in the table, that’s not true.

For example if I created a method to change the name of an employee :

changeName() {
  this.employees[0].name = 'New Name';
}

And then drive it off a button click :

<button (click)="changeName()">Change Name</button>

The name is updated just fine. Trackby is about redrawing the overall list Dom, not the individual elements in it.

Same goes if we add an item like so :

addEmployee() {
  this.employees.push(
    {
      id : 7, 
      name : 'New Employee'
    }
  )
}

And trigger it from a button click. Again, it’s just as responsive with a trackBy than without.

This is such a simple error but one that catches me out on every single new project it seems. The full error is :

Error: StaticInjectorError[HttpClient]:
StaticInjectorError[HttpClient]:
NullInjectorError: No provider for HttpClient!

Unfortunately it’s not that descriptive, but it’s an easy fix.

In your app.module.ts, you need to import the HttpClientModule.

Simply add the import at the top of the file :

import { HttpClientModule } from '@angular/common/http';

And then in the imports section, add the HttpClientModule :

imports : [
    HttpClientModule,
    //...Other Modules Here...
]

And that’s it! You only need to do this in the root AppModule and don’t need to reimport it elsewhere in other modules within your app.

In some very rare cases, you may need to call a child component’s method directly from a parent component. Generally speaking, this should be seen as only a last resort. Component communication in most cases should be limited to data binding (Both input and output), and and in some cases using a service to emit values between two components.

However, there has been times where I’ve had race conditions between two components that can only be solved by a very precise order of methods being called. This means that I need them to happen synchronously. For that, this method is a life saver , and it’s simple too!

Consider I have the following component :

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss']
})
export class ParentComponent implements OnInit {
}

And I also have a child component like so :

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
    callMe(value : string) { 
        console.log('Called : ' + value);
    }
}

Inside the view of parent.component.html, I place the child component.

<app-child></app-child>

Now inside my parent component, I can actually use ViewChild like so to get a direct reference to the child.

export class ParentComponent implements OnInit {
    @ViewChild(ChildComponent, {static : true}) child : ChildComponent;
}

Notice that I don’t pass in a “string” to find like we sometimes do with a ViewChild, we pass in the actual type of component we are looking for.

Then, it’s as easy as calling something on our child.

export class ParentComponent implements OnInit {
    @ViewChild(ChildComponent, {static : true}) child : ChildComponent;
	
    callMyChild(){
        child.callMe('Calling from the parent!');
    }
}

The usual ViewChild rules apply however that generally speaking, you only have access to ViewChild references after the view is initialized (So you cannot access them in an ngOnInit method, you have to use ngAfterViewInit).

Again, it’s typically much better to use data binding or a “joining service” for the two components to communicate. But often it can be hard to sync up the precise order of actions that need to happen. So for that, ViewChild is the winner.

Someone entering the world of javascript for the first time may be confused about the 3 different ways to define variables. var, let and const all seem to do roughly the same thing, so which one is actually correct to use? And why do we have all 3 in the first place?!

I wanted to write this guide as a really simple way to understand all 3, without having to read through RFC’s or really get into the nitty gritty as there’s actually a very simple explanation for which ones to use (And the one to not use!).

Pre 2015

You may be interested to know that before 2015, there was only the keyword “var” in javascript to define variables. I do want to add that in some transpilers, such as Coffeescript or early Typescript, there were different ways to define variables that didn’t strictly involve using the keyword “var”. But by the time they were compiled down to javascript, they themselves were using var under the hood anyway.

In 2015, ES6 was released and we were introduced to let and const in plain javascript. What I mean by “plain” javascript is that using the keyword let or const in a browser without something like typescript/coffeescript or a transpiler like Babel was a-ok.

Var Pitfalls

So now that we know let and const were introduced in 2015, the question becomes why they were even needed? Well let’s look at some examples.

var myVariable = "ABC";
var myVariable = 123;

Any beginner programmer will likely look at the above and think “Well, you’ve re-used the same variable twice, that should be an error. Then no less, the first time you used it, it was a string, then the second time an integer, so double errors please!”. And you would be wrong.

Var in Javascript allows you to re-use the same variable name twice, without an issue. On top of this, it allows you to assign different types to the same variable without a hitch. The latter is maybe not so much of a problem if you’re coming from something like PHP that allows similar problems, but the former is a big problem.

Let’s look at another problem.

myVariable = 5;
console.log(myVariable);
var myVariable;

You may think that this code is going to have big problems. I’m trying to use a variable before I’ve even declared it. But again, Javascript needs to be special with a feature called “hoisting”. What it means is that a javascript variable declaration is always “hoisted” to the top of it’s scope and can be used before it’s even been declared. This can lead to very unintended consequences and confusing behaviour.

As an example :

var myVariable = 5;
if(myVariable == 1)
{
    var myVariable = 2;
}
console.log(myVariable);

What will this example print? You may think it will print 5. As the initial declaration sets myVariable to 5, then only if it’s 1 will it enter the next block of code. But again, because Javascript hoists the inner declaration, this example will actually print 2.

Another example may look like so :

for (var i = 0; i < 5; i++){
  console.log(i);
}
console.log(i); //We might expect this to errors!

What we would expect in most other languages is that the second log would error because the variable declaration is within the loop. Incorrect! Hoisting again pulls the declaration to the top of the scope.

What you’ll find is that the mix of hoisting and being able to override existing declarations in Javascript without issue can often lead to very difficult to find bugs in code.

Using let

And of course, that’s where the keyword “let” comes in.

This now becomes an error :

let myVariable = "ABC";
let myVariable = 123;

But it’s important to note that this does not error even though we are changing the variable type :

let myVariable = "ABC";
myVariable = 123;

let is also scoped to (generally) be unique within curly braces. As an example :

for (let i = 0; i < 5; i++){
  console.log(i);
}
console.log(i);//Throws an error as I is not defined

I would note that using the let keyword gives you this sort of “optional” cascading affect where you can override in a child scope, without affecting the parent. As an example :

let i =1;
if(i < 5) {
	console.log(i);
}
console.log(i);

This prints “1 1” as the variable i was available inside the child scope.

However this code also has no problem compiling

let i =1;
if(i < 5) {
	let i = 2; //new line
	console.log(i);
}
console.log(i);

This prints “2 1”. Where the second initialization of i is set to 2 and printed, but it doesn’t affect the parent i.

In essence, let gives us plenty of the flexibility of var, but without the hoisting and without being able to re-declare a variable with the same name in the same scope.

Using const

Const has many of the same restrictions as the let keyword, but with a few more added on for good measure.

The const keyword does not allow you to re-assign a value to it, even if it’s the same type.

const myVariable = "ABC";
myVariable = "XYZ";//Error

Because of this, you also can’t define a const variable without assigning a value to it.

let myVariable; //No problem
const myConstVariable;//Error

Our example earlier where we were able to re declare a let variable inside a child scope also doesn’t work with const.

const i =1;
if(i < 5) {
	const i = 2; //error
	console.log(i);
}
console.log(i);

In this case, const is actually available in child scopes also, but it is not able to be “re-declared”.

Const is the most restrictive variable declaration type, but it allows us to be certain that after being declared, the value will never change.

So Which Should I Use?

Generally speaking, you should not be using var unless in extreme circumstances where you actually want hoisting (read : never).

So the choice comes down to let or const. Use const if you want to ensure that the value will never change. In general, it’s worth getting in the habit of using const as your default declaration as 9 times out of 10, the value actually won’t change. Then, only when you run into a roadblock where the value may actually need to be changed, switch the declaration to let.

Requesting “lookup” data from an API in Angular can quickly weigh your application down if you’re having to grab the same data over and over. The type of lookup data I’m talking about is say fixed country lists, or a set of user roles, or any other set of data that is rarely going to change on a daily, weekly, or even monthly basis.

I recently tried to solve this by implementing a level of caching in the Angular app that was purely in memory. I figured that if I cache everything in memory, then a simple refresh of the page “clears” the cache, but requests to grab any lookup data on multiple pages won’t result in multiple calls to my API. I also figured it was going to be the easiest way to approach things.

Avoiding Interceptors

There’s a tendency in Angular that when you are dealing with anything HTTP request related, you create an interceptor for it. I’ve been guilty of this in the past for sure! But the problem with Interceptors is that it’s a bit of an all or nothing approach. Opting out of interceptors is not that easy, and “configuring” when an interceptor runs and when it doesn’t is also a bit of a black box. For example, someone looking at a piece of that looks like so :

this.http.get(`myAPI.com`);

Does this cache your request? Does it run any interceptors at all? It’s hard to say without really digging into the code.

And don’t get me wrong, I do use interceptors a lot. But generally speaking, I try and make it so that in the overwhelming majority of cases, I want the interceptor to run. In our case, we only want to run the caching interceptor on a few select endpoints.

CachedHttpClient Service

Instead what I did is I created a CachedHttpClient that functions more or less like your regular HTTP service you already have in Angular.

The code :

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class CachedHttpClient
{
    cachedItems : any[] = [];

    constructor(private http : HttpClient) { 

    }

    getCached<T>(url : string) : Observable<T> {
        if(this.cachedItems[url])
        {
            return of(this.cachedItems[url] as T);
        }

        return this.http.get<T>(url).pipe(map((item : T) => {
            this.cachedItems[url] = item;
            return item;
        }));
    }
}

All this does is before running your HTTP call, we check if the exact URL is in the cache (This includes query strings also), and if not, run the http call, add the item to the cache, and then return the result. On the next request, it’s going to hit the cache and not have to make the http call!

We can inject it into a service like so :

export class MyService {
  constructor(private http : HttpClient, private cachedHttp : CachedHttpClient) { 
  }

  getLookupData() {
    return this.cachedHttp.getCached<LookupData>(`myAPI/LookupData`);
  }
}

Notice that it’s extremely easy to see what’s cached and what’s not. Not only are we using a class called CachedHttpClient, but the actual method call is “getCached”. There’s no hidden magic going on for a developer to shoot themselves in the foot.

Limitations

It is worth pointing out a few limitations.

If a user refreshes their browser (Or closes their browser), then the cache is lost. In my case, this is acceptable because I only really want to cache values as users move through the site. I don’t mind that when they do a hard refresh the first few pages have to fetch those values again and re-cache them. Infact, I somewhat like the fact that a user doesn’t have to know any “tricks” on clearing their “browser cache”, they just have to refresh.

And finally, the above code does not really handle race conditions all too well (e.g. If on a page, two components request the same lookup data). To me again, this was acceptable. Introducing some sort of lock mechanism was really overkill and in 99% of cases, you aren’t going to run into an issue where on one page, you request the same data at exactly the same time (Or you shouldn’t anyway!).

If you’re a C# developer moving to javascript, one of the very first things you’ll miss is the ability to write Linq on lists. While Javascript has a couple of methods to deal with arrays, some of them don’t quite match up to the power of Linq. Luckily, there is a great javascript library called Lodash which has almost everything you need! If you are interested in adding Lodash to your Angular project, you can read our guide here : https://tutorialsforangular.com/2020/08/02/using-lodash-with-angular/

I’m going to do this page cheatsheet style and simply list out the Linq method with it’s Lodash equivalent. Feel free to bookmark this page and come back to it when you start scratching your head thinking “I know how to do this in C#…” as quite often, it’s just a simple rename of your method and you are good to go.

My Models

For the sake of simplicity, the model I will be using will look like so :

{
    people : [
        {
            "firstName" : "John"
            "lastName" : "Smith"
            "age" : 30
        }
    ]
}

Lodash / C# Linq Cheatsheet

All

//C#
items.All(x => x.Age == 30);
//Lodash
_.every(items, x => x.age === 30);
OR
_.every(items, {'age': 30});

Any

//C#
items.Any(x => x.Age == 30);
//Lodash
_.some(items, x => x.age === 30);
OR
_.some(items, {'age': 30});

Average

//C#
items.Average(x => x.Age == 30);
//Lodash
_.meanBy(items, x => x.age === 30);
OR
_.meanBy(items, 'age');

Contains

//C#
items.Contains(myItem);
//Lodash
_.includes(items, myItem);

Count

Count how many match a predicate, not just the length of the array. Note that the return object for Lodash is essentially a group by on the predicate. For example with a collection with two items, one with an age of 30 and the other of an age of 31. The result is :

{
  false: 1,
  true: 1
}
//C#
items.Count(x => x.Age == 30);
//Lodash
_.countBy(items, x => x.age === 30);
OR
_.countBy(items, {'age' : 30});

Distinct

Note that in different versions of Lodash, the functions unique, uniq, and uniqBy have all been swapped around so you may need to try a variant of those depending on your lodash version.

//C#
items.Distinct(x => x.FirstName);
//Lodash
_.unique(items, x => x.firstName);
OR
_.unique(items, 'firstName')

First / FirstOrDefault

Lodash doesn’t provide functionality to either throw an exception like the C# First, or to return null like FirstOrDefault. Instead it will always return an empty array ([])

//C#
items.First(x => x.Age == 30);
//Lodash
_.first(items, x => x.age === 30);
OR
_.first(items, {'age': 30})

Foreach

//C#
items.ForEach(x => x.Age = 30);
//Lodash
_.forEach(items, x => x.age = 30);

Last / LastOrDefault

Similar to First / FirstOrDefault, Lodash doesn’t provide functionality to either throw an exception like the C# Last, or to return null like LastOrDefault. Instead it will always return an empty array ([])

//C#
items.Last(x => x.Age == 30);
//Lodash
_.last(items, x => x.age === 30);
OR
_.last(items, {'age': 30})

Max

Max in C# linq returns only the value of the property (e.g. If the max age is 30, it will return the value 30, not the actual array item). Lodash however will return the entire item that has the highest property value. If you want the entire item in C#, you have to use OrderBy/OrderByDescending.

//C#
items.Max(x => x.Age);
//Lodash
_.max(items, x => x.age);
OR
_.max(items, 'age'})

Min

Similar to Max, C# will return only the property while Lodash will return the entire item.

//C#
items.Min(x => x.Age);
//Lodash
_.min(items, x => x.age);
OR
_.min(items, 'age'})

OrderBy / OrderByDescending

Some versions of Linq only support sortBy which only sorts in ascending value. Similar to C#, orderby is stable, that is, the original order of the items is kept in tact and you must read the resulting object.

//C#
var sortedItems = items.OrderBy(x => x.Age);
OR
var sortedItems = items.OrderByDescending(x => x.Age);
//Lodash
var sortedItems = _.orderBy(items, ['age']);
OR
var sortedItems = _.orderBy(items,['age'], ['desc']);

Select

//C#
items.Select(x => x.FirstName);
//Lodash
_.map(items, x => x.firstName)

Skip

//C#
items.Skip(10);
//Lodash
_.slice(items, 10)

Sum

//C#
items.Sum(x => x.Age);
//Lodash
_.sumBy(items, x => x.age);
OR
_.sumBy(items, 'age');

Take

//C#
items.Take(10);
//Lodash
_.slice(items, 0, 10)

Where

//C#
items.Where(x => x.Age == 30)
//Lodash
_.filter(items, x => x.age === 30);

One painful thing when working with Angular is getting used to Observables vs Promises, and how some libraries use one or the other exclusively. It can be incredibly frustrating to add a library only to find it wants to force you into using promises, when the rest of your project uses observables.

But why would you use one or the other? Well…

You generally use an Observable if :

  • You are building something entirely for Angular as most of Angular uses Observables, it’s nice to keep to the same script.
  • You need to output more than one value over time/stream data, observables allow you to output multiple values while a promise can only output one.
  • You want to use RxJS operators such as map, tap etc.

You generally use a Promise if :

  • You are only ever going to return a single value
  • You prefer the “await” construct over using “then” or “subscribe”

In will get a feel over time as to which one you will need to use, but if you are using Angular, then chances are you will be sticking with Observables.

The real challenge comes when you have a library that will only return promises/observables, and your code is written completely the other way. Well never fear!

Turning Promises Into Observables

Converting a promise into an observable is rather easy with the “from” operator.

First, import “from” from the rxjs library :

import { from } from 'rxjs';

Then it’s as easy as :

from(myService.myPromiseMethod()).subscribe(x => console.log(x));

Be very careful that you use the “from” operator and not “of”. For example :

of(myService.myPromiseMethod())

This will return an observable but the value will be the promise itself, not the returned value of the promise. of is a really useful operator to return synchronous values inside your code, but should not be used for “unwrapping” promises.

Turning Observables Into Promises

If you thought going from a promise to an observable was easy, converting an observable into a promise is actually extremely easy with the “toPromise()” method available on every observable.

let myValue = await myService.getAll().toPromise();

There really isn’t much magic to it at all!

On almost every single Angular project after a certain size, you’ll start running into these errors :

An unhandled exception occurred: Call retries were exceeded

Or

JavaScript heap out of memory

Both of these point to the same issue. That your build process is hitting memory limits and simply crashing. It can be frustrating to debug for a few reasons.

  • Memory limits can be set for all NodeJS processes on a machine, meaning that what will build on one developers machine may not build on another because they may have already upped/lowered their memory limits.
  • Similar to the above, certain hosted build agents (e.g. Azure Devops, Github Actions etc), may have memory limits set lower/higher than you might think, meaning that builds succeed/fail here when they wouldn’t otherwise on other machines.
  • Non production builds of your angular project (e.g. Just using ng serve) build fine, but building with the production flag consumes far more memory, and so may crash only when building in production.

Luckily there is a really easy fix that gets around all of the above. While you can leave a note in the readme saying “Hey, you need to up your memory to XYZ”, a better option is to create a npm build script that sets the memory limit for that build only, and leaves everything else on the machine as is.

For example, a recent project of mine has these sets of scripts in the package.json :

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "ng build",
  "test": "ng test",
  "lint": "ng lint",
  "e2e": "ng e2e",
  "build-prod": "node --max_old_space_size=8000 ./node_modules/@angular/cli/bin/ng build --prod",
}

Notice the last script. It looks complicated but it’s actually quite simple.

  • Start the Node process.
  • Set the “max old space size” to 8000MB.
  • Find the angular CLI in your node modules folder.
  • Run an angular build of production.

Now anytime we need to build for production, we only need to run “npm run build-prod”, including on our build servers.

As to what you should set your memory limit to. You should try and set it relatively high, but not enough to consume all of your memory on your machine. By default, depending on your installed version of node, the default is between 500MB to 1GB. So even allowing up to 2 or 4GB should be enough to build most Angular projects.