DEV Community

Cover image for The "last mile" of functional-reactive web development
Dario Mannu
Dario Mannu

Posted on • Updated on

The "last mile" of functional-reactive web development

Telecommunication services have historically been made difficult by the last mile problem: the physical cables reaching subscribers' premises, difficult and expensive to connect, manage, upgrade and maintain.

Functional-reactive programming has been suffering a similar issue when dealing with HTML pages and templates.

When you create an application's logic, it's relatively easy to define a number of pure functions, their inputs and their outputs.

Sinking results to the DOM can't be done in a functional way, because HTML+JavaScript are not completely functional, so imperative code is needed.

const data = new Observable(observer => {
   setInterval(observer.next(getData()), 1000)
});

data.subsscribe(newData =>
 targetElement.innerHTML = newData
);
Enter fullscreen mode Exit fullscreen mode

What if there was, in fact, a way to use a functional programming style to achieve the same thing?

Turns out there is. A little library called Rimmel.js comes with first-class support for Observables, Observers, Promises, and all you need to keep a proper functional programming style.

const data = new Observable(observer => {
   setInterval(observer.next(getData()), 1000)
});

document.body.innerHTML = rml`
  <div>${data}</div>
`;
Enter fullscreen mode Exit fullscreen mode

In this example, we changed our approach from a "push" model, to a "pull" model. The template itself is pulling data from an observable stream, which we can leave as a pure function, and there is no imperative code for us to write in order to update the DOM. That part is done by Rimmel, which reccognises the observable and diligently sets up subscriptions and unsubscriptions behind the scenes for us.

No more explicitly setting of innerHTML, style, dataset, disabled, or other HTML attributes. Simply define variables, promises or observables, put them in your templates, and Rimmel will do all the binding.

The context tells how data needs binding.

  const template = rml`
    <div class="${anObservableThatEmitsClasses}"></div>
  `;
Enter fullscreen mode Exit fullscreen mode

This allows you to neatly separate data from presentation. Thanks to the purely-functional style of your code, it will be much simpler to test them in isolation without excessive relyance on mocks and stubs.

QA

Interested in testing? LeapingBunny is a library designed to test observable view-models using ASCII-art. That means even really complex unit tests take 2 lines of code LeapingBunny

Top comments (0)