One of the more frustrating limitations of vanilla JavaScript is that there is actually no GUID or UUID generator in the language. That’s right, out of the box, you cannot generate a GUID with a nice single line of code! Very annoying.

Luckily, there are two ways that I’ve used in the past to generate GUID or GUID-like strings.

This first piece of code is one I use in places where the randomness isn’t such a big deal. It might be just generating correlation ids, or just as a way to generate some randomized letters/numbers, but not global uniqueness and/or collisions aren’t such a big deal.

generateGuid() : string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0,
      v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

In most cases where I’m generating a GUID on the front end, I’m not worried too much about how secure things are. You shouldn’t be too concerned on collisions in the browser anyway because a user could just as easily inject JavaScript and/or modify an API call that uses the GUID into using their own string.

However, for a more secure GUID, there is obviously an NPM package for that!

npm install uuid

Then use the uuidv4 function to generate guids as you need them!

import { v4 as uuidv4 } from 'uuid';
let myGuid = uuidv4();

Again, in most cases I just use the first function. But I know people come up with all sorts of links on how “Math.random()” isn’t truly random etc. So both options are there!

An interesting question came up recently about the difference between the “optional” flag in Typescript, and setting something as null. More importantly, it was a question of whether the following were synonymous :

export class MyClass {
  myProperty? : string;
}
export class MyClass {
  myProperty : string | null;
}

The answer is no, these are not the same thing, but it took some explaining to do to people from backgrounds that do not have a “optional” flag, and instead just use a nullable type. For instance, in C#, we may do something like so :

class MyClass 
{
    public string? MyProperty { get; set;}
}

This tells the compiler/runtime that MyProperty is nullable, and by default, will have a null value if no value is given. However in Typescript, the question mark operator is *not* a nullable operator, it instead denotes whether something is “optional”. And there’s an important difference.

export class MyClass {
  myProperty? : string;
}

This says that the MyProperty is optional, and if no value is given, that the value will be set to “undefined”. It’s an important distinction because it’s not a “default” value, it’s “no value”. This is important because if you initialize the class like so :

let class : MyClass = { };

No error will be thrown because the property is optional.

When you instead do something like so :

export class MyClass {
  myProperty : string | null;
}

And then we initialize it the same way :

let class : MyClass = { };

We get the following error :

Property 'myProperty' is missing in type '{}' but required in type 'MyClass'

This is because while we are allowing null to be set as the value, it does not change whether a value needs to be set or not. It’s not optional. Therefore, if we use the discriminated union, we must pass in null as the initial value like so :

let class : MyClass = { myProperty : null };

Again, the most important thing about all of this is divorcing the idea that the question mark operator works the same as it does in C#. It is not a signifier of whether something can be null, it is instead used to mark something as optional. And that is an important difference.

When binding a dropdown/select list in Angular, you will come across two different ways of databinding, using [value] and using [ngValue]. They actually have a very simple difference. But let’s whip up an example first.

Imagine I have a component that holds a list of books :

export class AppComponent  {
  selectedBook : any;
  myBooks = [
    { id : 1, title : "War and Peace", author : "Leo Tolstoy" }, 
    { id : 2, title : "The Lord of the Rings", author : "J. R. R. Tolkien" }, 
    { id : 3, title : "Pride and Prejudice", author : "Jane Austen" }, 
  ];
}

Then in my view I have nothing but a dropdown, and I’m binding to the myBooks list. Also note that I’m using ngModel on the actual select to capture what is selected. And in this example, we are using the [value] attribute.

<select [(ngModel)]="selectedBook">
    <option *ngFor="let book of myBooks" [value]="book.id">{{book.title}}</option>
</select>
<br /><br />
The selected book is : {{selectedBook | json}}

At the end, I’m outputting my selected book in JSON format, just so we have some feedback on what we are selecting.

When I run this, everything works. When I select a book, I see the following :

Notice one thing however. Our “2” which is the id of our book is wrapped in quotes. This is the first thing you’ll notice about using [value]. [value] always binds as a string. Even if you pass it a number type, it will be coerced into a string.

You may not think this is a big deal at first. But if you are fully immersed in Typescripts strict typing, then this can cause unintended consequences because you may end up comparing strings and numbers (Or really any other type) when you never intended to.

That’s where [ngValue] comes in. Let’s change our binding to use [ngValue].

<select [(ngModel)]="selectedBook">
    <option *ngFor="let book of myBooks" [ngValue]="book.id">{{book.title}}</option>
</select>
<br /><br />
The selected book is : {{selectedBook | json}}

Now when we view our example in the browser :

No more quotes! This is because [ngValue] will bind any type and never try and convert things to strings.

Now obviously we are binding the id in our example. But often what happens is that you will require additional info about that item. So you end up querying the initial list to get say the title of the book. Ugh!

But remember, [ngValue] can bind keeping the original type in tact. So we can simply change our binding to be the entire book object.

<select [(ngModel)]="selectedBook">
    <option *ngFor="let book of myBooks" [ngValue]="book">{{book.title}}</option>
</select>
<br /><br />
The selected book is : {{selectedBook | json}}

Now, instead of just returning our id. Our selectedBook is the entire book object!

One final piece of the puzzle is that [value] will output HTML to the browser with the value intact like so :

<option value="1">War and Peace</option>

However if you use [ngValue], you instead get :

<option value="0: Object">War and Peace</option>

Because the binding is on an object. While this may not seem like a big deal (Who’s reading your HTML anyway?), it may be an issue if you use a browser automation tool such as selenium or cypress that is required to read the value of each option. So just keep that in mind!

In Summary :

  • Use [value] when you are binding to a string value and only a string value. Or you need access to the option value inside the HTML for automation purposes
  • Use [ngValue] when you are binding to any type and/or you want the entire option bound instead of just a string

I came across an interesting problem recently where I had to check if a date was before or after today. Getting todays date seemed trivial :

let today = new Date();

But in my test cases, things were blowing up, often at weird times of the day. And it occurred to me that I wasn’t just comparing dates, I was comparing the times on those date objects too!

Such is Javascript, there isn’t actually a way to ask a date object for *only* the date portion for comparisons sake, it always has a time component attached. So for example if I have something like so :

let someDate = someService.getTheDate();// Returns Sat Jan 16 2021 08:30:00
let today = new Date();// Returns Sat Jan 16 2021 9:30:00
let isSameDay = today == someDate; // False!

It’s comparing the time as well as the date!

A very very common pitfall is assuming that the method .getDate() on a Date object will return the date.. Well.. It does, but only the day of the month. So in our example, it will return 16 as in the 16th of Jan. But obviously if you are comparing dates across different months, this isn’t going to work!

So how can we compare just the dates? There is some.. shall we say… interesting fixes out there. One that seems the most prominent is to zero out the time portion :

let today = new Date();// Returns Sat Jan 16 2021 9:30:00
today.setHours(0, 0, 0, 0); // Today is now Sat Jan 16 2021 0:00:00

But the issue with this method is that your date object now has a zero’d out time so if you want to use it elsewhere, you should first clone the date object, then zero it out, then compare it. Something like so :

let today = new Date();// Returns Sat Jan 16 2021 9:30:00
let clonedDate = new Date(today);
clonedDate.setHours(0, 0, 0, 0); // Today is now Sat Jan 16 2021 0:00:00
console.log(today);// Still returns Sat Jan 16 2021 9:30:00

However, this setHours method didn’t sit well with me. It was somewhat ambiguous what it was doing, even with the cloning. So my prefered approach was actually to create a new date object using only the parts I cared about.

let today = new Date();// Returns Sat Jan 16 2021 9:30:00
let clonedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());

Then I can compare clonedDate to another date that we create using only the date portion, and the comparison works perfect!

One of the most infuriating parts of a new project setup is the npm install. A new Angular project from the CLI (Running “ng new”) can even take several minutes. And even if it’s an existing project that you know you have already setup, but you just want to check, a simple npm install can still take 30 seconds just to say “Yep all good here!”.

An option you see get thrown around often is to switch to using Yarn. Using Yarn from the command line is very similar to NPM (Infact we have a NPM vs Yarn Cheatsheet right here!), but what you’ll quickly find is that Yarn is so much more performant. The biggest reason is that Yarn has an offline global cache on your computer so repeated installs of the same package (For example, creating new Angular projects over and over again), will simply utilize the cached version rather than downloading the package all over again over the internet. Sounds good to me!

Adding Yarn after the fact to an existing project may be relatively straight forward. But what we are actually looking for is the ability to use Yarn with the actual internal angular cli when it tries to install a package.

Using Yarn Globally

If you want to use Yarn globally for *all* Angular projects on your machine, then all you need to do is run :

ng config -g cli.packageManager yarn

This updates the .angular-config.json inside C:\Users\YourUser on Windows to look like so :

{
  "version": 1,
  "cli": {
    "analytics": false,
    "packageManager": "yarn"
  }
}

Using Yarn On A Single Project

Sometimes you don’t want to globally use Yarn, and you just want to set it up on a new project you are about to create. This can be a bit of a headache as the initial call to ng new is the the most painful part of the entire process as it will use npm to install all the base packages, even if once the project is setup you switch to Yarn.

But we have a bit of a cheatcode to get around it!

When creating our project we can run :

ng new --skip-install

Where the skip install flag will actually skip over the final npm install after creating the project. From there, we can run the following command *from inside the project* :

ng config cli.packageManager yarn

Notice how we don’t have the -g flag like before. This sets up yarn as the package manager for this project only. From there, we just run

yarn

And the initial install of Angular components will happen like they normally would on an ng new command, but using Yarn instead.

While many API’s allow you to upload files via multi-part POST forms, others prefer to stick with a pure JSON approach and accept uploads in base64 format allowing you to always be sending and receiving JSON. This means that if a user selects a file in your Angular app, you need to be able to convert that file to Base64 before sending it on.

I thought this would be a rather trivial task but there seems to be some really complicated ways to do what seemed simple at first. Many examples tried to use async/await and promises, but Angular really prefers observables. Ontop of that, people were using an API that was not actually about returning base64 strings, but returning DataURI’s which are very close, but some browsers return the result as data:base64here rather than just the base64.

Anyway! The actual code looks like this. In my view I have :

<input type="file" (change)="onFileSelected($event)" />
<br /><br />
base64 Output : <br />
{{base64Output}}

And in my code behind I have :

export class AppComponent  {
  base64Output : string;

  onFileSelected(event) {
    this.convertFile(event.target.files[0]).subscribe(base64 => {
      this.base64Output = base64;
    });
  }

  convertFile(file : File) : Observable<string> {
    const result = new ReplaySubject<string>(1);
    const reader = new FileReader();
    reader.readAsBinaryString(file);
    reader.onload = (event) => result.next(btoa(event.target.result.toString()));
    return result;
  }
}

Notice a few things about the code.

  1. FileReader is event driven. e.g. You can’t say “Load this file” and then immediately get the result. This means that we either have to use promises or observables, because we are using Angular, let’s use observables.
  2. We use a ReplaySubject because we only need to calculate the file once. e.g. If we subscribed multiple times to the same return subject of this method, it doesn’t need to recalculate the base64 since it’s deterministic (The same file is always the same Base64 string).
  3. I saw some guides saying to use reader.readAsDataURL(file), but again this had weird issues in some browsers. It’s better to load the file as per normal, then use the btoa function to actually return Base64 without any other gunk in the response.

Hopefully that makes sense!

Take, First, and Single all appear to be almost identical in RxJS/Angular at first glance. But actually, they have some very important differences that could throw up some very weird errors if you aren’t expecting them. If you have spent any time working with C# LINQ expressions at all, you may actually find a bunch of this familiar.

In anycase, let’s jump right in.

Take(1)

Take(1) is the easiest of the three. It simply takes the first value output by the observable, then unsubscribes itself. As an example :

let myObservable = new Subject();

let subscription = myObservable.pipe(take(1)).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.next("Foo");
myObservable.complete();

console.log(subscription.closed);

The output of this would be :

Foo
True

As we subscribed, output the value, then the subscription is closed. However consider the following :

let myObservable = new Subject();

let subscription = myObservable.pipe(take(1)).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.complete();

console.log(subscription.closed);

Notice how we don’t call next on our observable at all. Well the output of this is still :

True

As we still abide by the observable being completed regardless of whether we got any value from it. Also consider the following :

let myObservable = new Subject();

let subscription = myObservable.pipe(take(1)).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.next("Foo");
myObservable.next("Bar");
myObservable.complete();

console.log(subscription.closed);

This still outputs

Foo
True

Because we are using take(1). We are unsubscribing from the observable so any additional values are not pumped to the subscription.

First()

Now consider the following with First() :

let myObservable = new Subject();

let subscription = myObservable.pipe(first()).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.next("Foo");
myObservable.complete();

console.log(subscription.closed);

This outputs the same as earlier.

Foo
True

But consider the following when we don’t call next on our observable :

let myObservable = new Subject();

let subscription = myObservable.pipe(first()).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.complete();

console.log(subscription.closed);

We actually get :

Foo
ERROR : no elements in sequence - EmptyError

Why? Because we closed off our observable before even the first value was output. This may seem like an actual worse feature to have, but it’s an important distinction. If you are always expecting at least one value, then you may use first() to log errors when you don’t get any data. It’s almost signalling the intent of the code that there should always be atleast one value coming from the observable.

Finally, also consider the following code :

let myObservable = new Subject();

let subscription = myObservable.pipe(first(x => x == "Bar")).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.next("Foo");
myObservable.next("Bar");
myObservable.complete();

console.log(subscription.closed);

Notice how we can pass a matching function to our first operator to tell us to only match on a certain value. This is an added piece of functionality that take(1) cannot do on it’s own!

Single()

Single is very similar to using First() in some ways, with an added restriction. Consider the following :

let myObservable = new Subject();

let subscription = myObservable.pipe(single()).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.complete();

console.log(subscription.closed);

This also throws an error just like first() because we are completing the observable before any values are output. But also consider the following :

let myObservable = new Subject();

let subscription = myObservable.pipe(single()).subscribe(x => {
  //Do something with the data. 
  console.log(x);
});

myObservable.next("Foo");
myObservable.next("Bar");
myObservable.complete();

console.log(subscription.closed);

This results in a new error :

ERROR Sequence contains more than one element

While first() will simply take the first value and ignore all others, single() will take the first value but will throw an exception if there is more than 1 available. This is an important distinction because again, it signals the intent of the code that we are expecting 1, and only 1 value. If there is more than 1, then something as gone wrong and we should throw an exception.

A common pattern when working with observables/subjects inside an Angular Component, is to store the subscriptions in a list, and then unsubscribe when the component is destroyed.

Now I’ve seen many developers not bother unsubscribing at all when it comes to HttpClient requests, but it’s a good habit to get into as more often than not, you will get to a point where you are using Observables/Subjects for more than just simple API calls, and then you will really need to unsubscribe!

A common example of how many developers implement this is like so :

export class AppComponent implements OnInit, OnDestroy {

  subscriptions : Subscription[];

  constructor(private myService : MyService)
  {
  }

  ngOnInit() {
    let subscription = this.myService.getData().subscribe(x => {
      //Do something with the data. 
    });
    this.subscriptions.push(subscription);
  }

  ngOnDestroy() {
    this.subscriptions.forEach(x => {
      if(!x.closed) {
        x.unsubscribe();
      }
    });
  }
}

A better (just in my opinion) option is typically to use a simple boolean variable to close off all subscriptions when the component is destroyed. This is used in conjunction with the takeWhile operator of RxJS like so :

export class AppComponent implements OnInit, OnDestroy {
  isAlive : boolean = true;

  constructor(private myService : MyService)
  {
  }

  ngOnInit() {
    this.myService.getData().pipe(takeWhile(() => this.isAlive)).subscribe(x => {
      //Do something with the data. 
    });
  }

  ngOnDestroy() {
    this.isAlive = false;
  }
}

This is a better option in my opinion because you don’t need to keep a list in memory of subscriptions and there is slightly less boilerplate code going on. But still, we have to litter our components with this “isAlive” flag everywhere, and remember to add an ngOnDestroy that sets it to false. You could create base components that exposes this flag, but it’s still a bit of boilerplate that you could do without.

What we really are looking for is a nice library to do all of this for us. As it so happens, I found one called “TakeWhileAlive”. It’s NPM page is here : https://www.npmjs.com/package/take-while-alive. At first this worked great! That is, until I deployed it into production and started seeing weird happenings. As it turns out, it doesn’t work once you deploy the project in production mode : https://github.com/joostme/takeWhileAlive/issues/2 doh!

Luckily, that Github issue pointed me to another great library. “TakeUntilDestroy“. It works like this.

If Angular 8 or below :

npm install ngx-take-until-destroy --save

If Angular 9 or above then :

npm install @ngneat/until-destroy

Then inside your component, if you are using Angular 8, you only need to do the following :

import { untilDestroyed } from 'ngx-take-until-destroy';

this.myService.getData().pipe(untilDestroyed(this)).subscribe(x => {
  //Do something with the data. 
});

And that’s it. The one caveat is that you *must* have an empty ngOnDestroy method, even if it’s not being used. The library will throw an error if this is not the case. But otherwise, you will now auto unsubscribe without any additional boilerplate just by adding untilDestroyed onto all of your subscriptions.

Now for Angular 9+, things are a little more complicated, but still rather easy. The only additional logic you need is to add a single attribute onto your component like so :

@Component(...)
@UntilDestroy()
export class AppComponent implements OnDestroy {
 //...
}

Notice how we added UntilDestroy() onto our component. Then we still add untilDestroyed(this) onto our subscriptions similar to Angular 8, and we will auto unsubscribe when our component is destroyed.

I’ve seen some diabolical ways Angular developers have tried to “subscribe to an observable.. but return that same observable”, or at least that’s how it was explained to me when I saw the following code :

getData() { 
  let observable = this.myService.getData();

  observable.subscribe(x => 
  {
    //do something with the data here
  });

  //Also return the observable here. 
  return observable;
}

This is very bad practice for a very simple reason. Each subscription to an observable, for the most part, will execute the observable method. Remember, observables are typically lazy loading and therefore execute only on a subscription. But they also execute *every* subscription.

In the above code, should someone subscribe to the observable returned from the method, it will also execute the underlying observable. If this is an API call for instance, you will end up calling the endpoint twice.

So what’s the right way to do this? It actually all depends on how getData() is being called, and what you need the data for *inside* the method.

If You Need Access To The Data You Will Then Return Anyway, Use Tap

We actually have a full article on how the Tap operator works right here. But if we take our above example, it would work a little like this :

getData() {
  return this.myService.getData().pipe(tap(x => 
  {
    //Do something with the data here. 
  }));
}

This works if you need access to the result (For example for caching), but you don’t intend to edit the result (For example map it to another type). And the caller to getData() should just get whatever the result from the service was.

If You Need To Modify The Result Before Returning, Use Map

This one is again pretty straight forward :

getData() {
  return this.myService.getData().pipe(map(x => 
  {
    return new MappedClass(x.value);
  }));
}

We use Map if we want to modify the result before returning it to the caller. It should be noted that again, if you don’t want to manipulate the result at all, then use Tap.

If The Caller Doesn’t Need The Result At All, And May Or May Not Subscribe, Use Replay Subject

This one might be a bit complicated, but here it is :

getData() {
  let subject = new ReplaySubject(1);

  this.myService.getData().subscribe(x => 
  {
    //Do something here. 
    subject.next();
    subject.complete();
  });

  return subject;
}

We create a ReplaySubject that has a buffer size of 1. (For why we use ReplaySubject here and not Subject, see here). Then then call the service, and on the completed subscription, complete the ReplaySubject, letting any callers know (If they care at all!) that we are done.

This has a couple of benefits :

  1. The call to the service is made regardless of whether this method is subscribed to or not. For example if you are calling this on button press (Where you don’t care about the result) versus calling it somewhere else in your component (Where you do care about the result), it doesn’t matter.
  2. The ReplaySubject is import as the call to myService might complete before a subscription is added to the returned subject.

I do want to point out that on the original subscription, you may need to unsubscribe/complete the observable returned from myService, but the point stands that a ReplaySubject can be a great way to let a caller subscribe “if they want”, but if they don’t things still run fine.

If The Caller Is Marked Async, Or You Prefer Promises, Then Use Promises

This is certainly not ideal. In most cases, you should try and stick with using Observables in an Angular application. But if you really need to, you can switch to promises *if you are sure there will be no negative side effects* . The most important being that you understand that how promises and observables can be very similar, but do have some distinct differences.

The code would look like so :

async getData() {
  let data = await this.myService.getData().toPromise();

  //do something with the data. 

  //return the data if we want. 
}

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!