So far we only had effects that write something to the external world, we are not yet reading anything from the external world into our app. This lesson shows how we can change the DOM Driver to return a "DOM Source" representing read effects, such as click events. We will leverage that to create an interactive application.
Now we have a system with main and drivers, where drivers are responsible for making effects happen. But if you notice carefully, we only have effects that write something to the external world. We're not yet reading anything from the external world into our app. Eventually we need to do that.
For instance, say you need to read from local storage, or you need to receive user events such as clicks. All of these are read effects that the main should be able to take in.
Main is now a function that only returns an output, it still has no input. Notice also that the driver only takes input but it doesn't return anything as an output. That's because the output of main, the syncs, are the inputs to the drivers.
So if we want to make a read effect then we need to return something from the driver. We're going to call this actually DOM source. We need to create that DOM source somehow later. We're going to feed in the DOM source to the main.
Where does the main source and sync come from? These are dataflow network terminologies where source can be thought of input or read effects, and sync is an output or write effect. We need to get that DOM source there so we need to create here somehow. We want the DOM source to contain read effects on the DOM. User events such as clicks and keyboard strokes, they are all read effects on the DOM.
We can actually create an observable here called DOM source, which will have all of the clicks happening on the DOM, so document and click. This will return us an observable which has all the clicks happening on the DOM. Then we still are not feeding this back to the main, because every time we call a driver -- and this is driver function -- we get an output like we're getting here from the DOM driver.
Let me just simplify -- let's not think about the iterator just yet, let's go back to the hard-coded version where we call the DOM driver, like this, giving the DOM sync. Then as we saw we will get the DOM source as an output. Now we just need to feed back the DOM source into main.
But, this is quite tricky because DOM source is still undefined in this line, so this will not work. That's because this problem is sort of analogous to A is F of B, but then G of A.
So there's a cycle going on here where we need B to make A, and we need A to make B, and that's actually where the name Cycle.js comes from. The core of the idea is that there is a loop or small cycle between drivers and the main. So how do we solve that? A is an observable and also B is an observable. If we actually instead of using B, we could use something like B proxy here. Because B proxy is now available for F as an argument.
Then that helps us to make A, and then given A we can make B. Then now that we have B, we can feed back all of the events that happen on B into B proxy. So that's what we're going to try to achieve.
How do we do that in practice, is instead of using DOM source, we're going to use a proxy DOM source which is an RxJS subject, which is basically an observable that has nothing happening, and then you can manually insert events into it.
Now we have the proxy, we can get the syncs, and then we can get the actual DOM source. So we need to do is subscribe to this DOM source, get every click that is happening there, and just feed it back into the DOM source manually. So this onNext just pushes the event into this proxy observable.
Now every time we click on the DOM it will come here as DOM source, and now we can use that. Let's try using it, let's say we can restart this timer every time it's clicked. How would we do that?
Well, we can get the click, and we can flatMap latest, each of these clicks into a new timer like that. We can also start with the fake click. OK, so now every time I click on the DOM it restarts the timer. That's because I was able to get all the clicks happening on the DOM as a source and I was able also to write to the DOM based on these clicks that I make.
We did create some messy code here, but we're going to see how to clean it up on the next lesson.