The Process of Learning How to Use Observables in Angular is Terrible.

Why creating observables doesn’t help you use them in the wild, and my process on how I learned to use them.

Joshua Keith Pearson
The Startup
7 min readNov 18, 2019

--

Introduction

I can’t tell you how many hours I have spent googling the same, similarly, or unknowingly unrelated searches, trying to find a simple answer to a simple question:

“I have an observable with data I need. Now what do I do with it?” -Me, the last 6 months.

Search after search, time after time, I was hit in the face with answers that were of no help. Ranging from the angular docs themselves and their wisdom on creating and subscribing:

“Here’s an example of creating and subscribing to a simple observable [code for creating observable that emits a few numbers]” -Angular docs

to popular and obscure YouTube videos… parroting the exact same thing.

“Create an observable that emits thatShiz. Now subscribe to it and console.log(thatShiz)” -All YouTube tutorials on observables ever.

Cool. With this newfound knowledge, I can now create an observable and tell it to emit 1, 2, then 3 and then subscribe and console.log 1, 2, and 3. Whoopie. I don’t know if it’s because I am stupid and can’t see how that relates to my Firebase service returning an observable with data I need to be able to access, or if it’s because learning how to use observables by creating them yourself is about as pointless as learning how to change a bike tire when learning to ride the bike itself. In my extremely annoyed point of view, I think it’s pretty useless to teach someone how to create an extremely simple observable when all they need to know is how to use, get data from, and prepare for data with an observable that has data from an “unseen” source.

Background (and disclaimer)

I am self taught. I know that means I likely have holes in my education, but I was born in self-education. Molded by it. I didn’t see a coding class until I was already a man, by then it was nothing to me but a bunch of… Extremely outdated information. 🤷 You get the point. I don’t have a formal CS education as my main background. Like most of us, I learned that doing projects is the best way to learn new things, and so, a few months back I decided I wanted to pick up Firebase a bit, since google has a nifty free plan that is perfect for learning. I like noSQL stuff, and angular has a great integration for firebase. Or so I’ve read. My experience learning the details has been pretty sad, which is likely my own fault. Either way… The struggle is real, and if this silly little article helps even one person figure observables out, great. The information I share here is what I have learned, and I accept corrections where I am wrong. Feel free to let me know why I suck, and I’ll do some learning. That said:

Why the heckin would I use an observable?

Long story short, because you have one and need to. Let’s talk background. We require a different way of thinking when approaching observables, and they streamline protecting our data. We’re mostly used to an object or value as being set: item = {name: "item"}, which then exchanges hands: item = getItem(), and is retrieved multiple times: <h1>{{item.name}}</h1> , or by import if allowed.

Because of this, we have to manually code in protections, making things immutable with const, etc. When each component looks at a value, for instance, we have to (or should) be looking for a specific data model and type, ensuring the information is the correct type and that it’s not empty, and then displaying it, in every instance.

An observable, however, is different. It is a pipeline to the original value that is retrieved only once, therefore you only need to verify it once. The observable doesn’t change the value(s), it doesn’t share the value(s), it doesn’t copy them, rather it passes along (emitted) changes to the value(s), including the initialization of the value(s). In this way, observables protect an object: person = {name: "john", age: 55} from being redefined: person.name = "bruh" This is useful.

I won’t go into the benefits of reactive programming. There’s plenty of peeps who will chat all day long about that.

Using someone else’s observable (cause you rarely create one yourself)

Alright. Knowing why it’s nice is nifty, but how do you fracking frack an observable? I recently did a simple firebase app, I used that spaghetti-code as a reference when making the following example code. Disclaimer: This code is not working because it was not intended to work. This is not a tutorial on how to use firebase, either.

You have this service. This service gets a customer collection from firebase. All that you need to know is that this service is getting an observable of a collection (think of a table if you’re unfamiliar with noSQL DBs like firebase) the configuration of which is found in your firebase config elsewhere.

This component then gets that customer collection observable from the service, and then loops and displays each customer through the template’s ngFor loop, since the collection is made up of an array of objects that have a name location balance and an id .

This works because the initial value is populated and emitted from the firebase in the constructors, through customers$ down to the template where it is displayed. But, what if you want to get the information that was emitted prior? What if you want to get the information as it is currently in this database, edit it, then push those changes up to the database after the data has been initially displayed, on demand? That’s when things start getting tricky. You see, as I have said, observables don’t contain the data, they only pass along the changes, so when we have to start working with old data using a late subscriber, we ask ourselves: Where do we get the previously emitted data? As it stands now, that data is no longer in the observable. Let’s fix that.

Making an observable your own.

An observable is just watching a stream of data. You can’t pull data out of it (because it’s asynchronous), so declaring a let dataFromObservable; and then trying observable.subscribe(value => dataFromObservable = value) won’t do jack because when you subscribe, data hasn’t necessarily been emitted at that time. Think Schrodinger's cat as (probably) being dead when you subscribe, alive when things are emitted.

With that in mind, let’s make one small change to our above example in the service.ts file and introduce piping the shareReplay() method with the observable. Remember, this observable was returned by the firebase get request, in order to retrieve the “replay” (think snapshot) of the prior data that was emitted, we use the pipe method shareReplay(). Also, we’ll add a delete method to the service we made:

Now, we can add a delete method to our firebase component, ensuring that we unsubscribe from the observable so the delete method doesn’t get triggered every time a value is emitted through the customer observable.

So what happens here? Why did shareReplay() change so much with the observable? The delete function was all sorts of buggy prior to adding the shareReplay(), but works now. Think of it this way. An observable is the pipe in this crudely made demonstration:

The publisher (the firebase get collection request) watches for changes, then emits those changes down the observable to each subscriber. Nothing flows when there are no changes, so nothing is triggered.

Now, this is an observable that has the shareReplay() method.

Think of the urDataHere block as some sort of whiteboard. Every time a value runs down the observable to the subscribers, that whiteboard is erased and the value of the emission is written on it, depending on how you configure the shareReplay(). When a late subscriber subscribes, they’re given the shareReplay() data (what’s on the whiteboard) before or while being attached to the pipeline, then they just get information from the pipeline as data is emitted as usual.

Therefore, a late subscriber does not miss out on all the nice emissions from a bygone… event, and you can then do things like modify and delete requests on a database. I’ll not get into setting buffer size and all that fancy pants shareReplay()stuff.

Disclaimer

This whole path took me several weeks to figure out. Likely 10–15 hours total. I felt like the only information out there is either eli5 in the extreme, to the point of uselessness, because basically no one learns how to use an observable by creating one, or it’s so incredibly in depth and abstract that I wasn’t able to understand it enough to adapt it for my needs. For Pete’s sake, I didn’t even know what they meant when they said “data is emitted” when I had to do something with my first observable.

Outro

Thank you for attending my ted talk. (this article is in no way affiliated with tedx). I hope that this contributed something of value for you.

--

--

Joshua Keith Pearson
The Startup

A self-taught web developer and current full-time automation engineer.