I always believed that analogies are a great way to understand something. Whenever I was trying to actually get my head around a certain concept, I was always trying to find the right analogy for it. This could be anything, literally any concept that you can think of; from the way our solar system works to the way popcorn always gets stuck between your teeth.
Back when I was trying to grasp the concept of Observables & Rx, I remember saying to myself “huh, observables are kinda like Santa’s workshop”. Before you start throwing stones at me, please let me try and explain myself. When I was thinking of observables, I was thinking of streams of data. Sure, to a seasoned developer a “stream” might mean a lot, but to me it was something that I couldn’t fully understand. The above analogy, even up to this day, is how I translate “streams” inside my head.
In Santa’s workshop there is a conveyor belt that moves the presents around the different departments & corners of the workshop. The presents on top of this belt are actually a stream, an Observable. If you were a standing still in front of the belt you would see these presents passing in front of you in the course of time, just like data would be added to the stream in the course of time. These presents can either be “running” infinitely or can be stopped by a certain event (i.e. we have reached 500 presents). Similarly, you can either have a stream that will constantly accept new data or you can restrict it (and thus end it) based on certain conditions.
As the present pass from one place to another inside the workshop, they first get wrapped in paper, then they get pretty bowties, then cards are added and all sorts of things. These operations can also be applied to streams. Rx operators can alter the data (presents were put in boxes), merge data together (2 presents in a single gift box), filter data (throw away the faulty presents) and much more. It’s worth mentioning, that most Rx alterations create new streams and leave the original stream intact. This is a subtle difference from our Santa’s lab, where all work was done in the same conveyor belt (stream). You can think of it as “cloning the whole belt with the presents” and then performing these changes only to the presents on the cloned belt.
These gifts eventually get logged by a leprechaun, which inspects & counts all the gifts in the conveyor belt. Each time it sees a new one, it checks it & updates the number. It’s worth noting that if the leprechaun is not there, then the belt doesn’t even start moving (since none would allow an unsupervised belt to run). This is what Subscriptions and Observers are all about. We can subscribe to streams so that each time a new item is added to the stream we perform an action. Streams are lazy; if no subscriptions are active, then the stream won’t emit any values at all! Subscribers are event listeners, where the event is the arrival of a new datum. The most intriguing part is that this datum can be anything! Literally anything!
It’s worth noting that Subscribers and Observers are almost the same thing (Subscriber extends the Observer class), with the subtle difference that the Subscriber can unsubscribe from the stream any time it wishes.
Ok so, how can you create a stream? Well you can either do it from a list of data (i.e. [1,2,3] which will result in a stream of values 1, 2 & 3), you can create it from DOM events (i.e. each click event will be an entry to the stream of click events), you can even create a stream with exactly 1 predefined value (i.e. “15”).
What about more customised streams you ask? Well I saved the best for last. What if the leprechaun didn’t actually stand and watch the presents continuously passing in front of him, but yelled “next” each time it wanted to processes a present for inspection & logging? That’s where Subjects kick in. Simply put, Subjects are Observables & Observers at the same time. They can define a — usually initially empty — stream and then they can dynamically “push” data into the stream whenever they wish by calling
subject.next(datum) . This opens extremely interesting possibilities since now you can define an empty stream and then — whenever you wish — add whatever thing you want to the stream in order to be processed by the subscribers/observers. A stream can have as many subscribers/observers as you wish, thus what you actually create is a global event listener, listening to whatever you want to “push” and informing all of its subscribers of what got pushed into it. Reactive programming is all about the notion of “What stream can I create and subscribe to, in order to …”. I won’t go into detail on this article since there are a ton of other articles out there capable of teaching you that.
My intention for this article is to provide a slightly different view to a concept usually explained using complex terms. Analogies work for me so they might work for someone else as well, plus they give you a reason to think about Christmas and everything is always better when you associate it with Christmas 🙂