While there are many cases where we often believe that an RxJS Subject is necessary, there is a way of avoiding them. In this lesson we will see how to identify the underlying source of data and convert it into an Observable, essentially eliminating the use of an error-prone Subject.
[00:00] There will be times where you think you need an RX subject, and still it is possible to avoid them. In this case we have a subject, just a generic one without a proper name, and we're implementing a simplified analytic system. Basically, whenever a click happens, we're sending in the event of number 1 into that subject, or whenever a request comes back from the server as response, we're also sending in a number 1 to that subject.
[00:27] Then we can accumulate all of those number 1s as this X with the scan operator, and we can make this sort of count observable. Just to illustrate how the system works, whenever an event like response comes back from the server it registers, or whenever I click it will increment that. It's basically just counting all of the events that happen in my system, whether they are clicks or responses. Now the way that we can avoid the subject here is by identifying our original source of data, just asking ourselves where does the data come from?
[01:01] We know that it comes from clicks. It's converted to the number 1, and then it's accumulated, so we know that it comes from the clicks. Let's just first write here our steps. We first identify the sources of data, and then we convert those sources of data to observables.
[01:20] After we have observables for those sources, we can just compose them with all of the operators that we know. For instance, here we need to make an observable for our source data which is clicks, so we can make that with the from event, and click type, so that's our source of data.
[01:44] We also know that data may come from the server as a response. We also need to convert this into an observable. Let's make that as response observable, and we can make it from a promise by calling from, and passing in that promise there. Now this is one of our sources of data as well. Now that we have these two sources of data, we can compose them in different ways.
[02:14] We can make a stream here called oneObservable which will represent those number 1s that we were sending. It's basically going to be a merging of click stream and response stream, so we're basically saying that 1 is either events from click or either event from the response observable, and we're going to map each one of those to the number 1. We don't really care what is the contents of the click, or the contents of the response, we just want to convert that to the number 1.
[02:50] We can get rid of our subject, and we can use here oneStream instead. This is going to work just like before. When we run this, it gets the number 1 to represent the response. As we click, it will register those as well.
[03:06] If you want to make this slightly simpler, we can also cut out the middle man and just put in here straight merge, and then map. Now this countStream is basically either events from the clickstream or the response stream, and we're just mapping each one of those to the number 1, and then we're accumulating them over time.
[03:30] The lesson here is try practicing by identifying where does your real data come from, and then asking yourself, "Can I wrap that in an observable?" When those things become observables like here, your code base will be more predictable because you can know where is the data coming from, and where it is flowing without having to hunt down all of the calls to subject.next method.
const count$ = Observable .merge(click$, res$) .mapTo(1) .scan();