When writing a complex single page web application, you find yourself dealing with A LOT of asynchronous activities. The user is busy clicking on UI elements and typing in text boxes. Asynchronous requests and responses are flitting back and forth between the server and client. Perhaps you’ve even got asynchronous messages coming from web workers.
Managing all of this asynchronous information and maintaining the correct state can be a real challenge. Luckily there are a number of libraries out there to simplify the task.
On the project I am working on, we are heavy users of KnockoutJs and Reactive Extensions (RxJs). These two libraries work so amazingly well together and once you learn how to use them effectively, building complex user interfaces becomes quite simple and straight forward.
When programming a UI, you are typically maintaining various pieces of state. You need to ensure that all of this state is updated correctly in response to various events.
In a traditional imperative programming style, you do this by writing an event handler for each event that one, by one, updates all of the state variables (including UI elements) that needs to be updated in response to the event. This includes state variables directly affected by the event, as well as those indirectly affected. This approach leads to a common type of bug that results from a developer forgetting that some state variable is indirectly impacted by an event and doesn’t update it. Or updates the state in the incorrect order.
In a reactive programming style, you define the relationships between the different state variables (including UI elements). Often you need not even write an event handler, but if you do need to write one, you only need to update the state directly affected by the event. You rely upon the framework to propagate the changes to any indirectly affected state variables by following the relationships you defined. This approach avoids the problem of not updating all of the state correctly. As long as you setup the relationships correctly, the infrastructure will ensure everything is updated.
At first glance, the 2 libraries seem similar. Both libraries implement the Observer pattern after all. But they have a different focus.
KnockoutJs focuses on two-way binding between UI elements and your view model properties. Thus it really focuses on observing values. Its ko.computed method provides a very simple and powerful way to derive values from each other. Because it is focused on two-way binding between an element and a view model property, Knockout observables are both readable and writeable. The UI’s read model is the write model. It is easy to use Knockout to write the “V” and “VM” portion of a MVVM UI.
RxJs is focused on receiving and managing streams of asynchronous information. It is really about observing sequences of values. Because of this focus, it comes with the full power of LINQ, with dozens of simple operators that can be applied to a stream of asynchronous data to transform, aggregate, join, filter the data as it arrives. Also, because of its focus on sequences of data, it can produce notifications when a particular sequence completes, or when an error occurs in the source. It does not really support bi-directional observations. If you want bi-directional communication, then you must setup a pair of observables, one for reading and one for writing. It is well suited to CQRS style of programming, where your read models are separate from your write models. It is well suited to writing the “M” portion of your MVVM UI because it provides a natural way to handle the success/failure of your various asynchronous requests to the server.
Going forward, I’ll be writing a series of posts showing some useful techniques and examples of using RxJs and KnockoutJs together to write truly reactive code.