DEV Community

Cover image for Reactive Streams: Functional vs Imperative
Dario Mannu
Dario Mannu

Posted on

Reactive Streams: Functional vs Imperative

You may already know how functional programming is different from imperative, but... what if it's stream-oriented? Did you know it can be both?

You may be familiar with the functional+reactive paradigm popularised by ReactiveX and RxJS, in which you create streams more or less like this:

const stream = new Subject().pipe(
  map(x => x+1),     // increment
  filter(x => x&1),  // pass through if odd number
);
Enter fullscreen mode Exit fullscreen mode

However, some people still find it difficult to remember many of the available RxJS operators.

Imperative programming to the rescue! You can actually write stream-oriented applications on the front-end using plain vanilla JavaScript steps. Let's see how:

// this is a stream
const stream = flow(

  // this is a step
  cf => data => {
    const incremented = data +1;

    if(x&1) {
      cf(incremented);
    }
    // else... we just don't
    // make a call forward
  },

);
Enter fullscreen mode Exit fullscreen mode

Et voilà! We just created a simple, imperative-reactive stream. It combines both the previous map and filter logic in a single step, it's still relatively easy to test/compose and benefits from the stream-oriented goodness.

Reusable Steps

Streams really shine when you have something to compose, when they become some multi-step operations where you can reuse the same useful steps across different streams.

Let's now reformulate the above, but in imperative style, this time, using separate steps:

const inc = cf => data => cf(data +1);

const odd = cf => data => {
  if(x&1) {
    cf(incremented);
  }
);

const stream = flow(
  inc,
  odd,
);
Enter fullscreen mode Exit fullscreen mode

Great, now what? We are back almost where we started, aren't we?
We have a specialised version of map and filter.

Actually that's not bad: if those are useful and efficient for you, maybe you created them yourself, it's much more likely you'll remember those rather than stuff like the switchScan from RxJS (a highly specialised operator used in very rare occasions).

Did you notice how streams created this way resemble the middleware used in Express.js? In fact, it's the same pattern.
In Express you call a next() function, here we just refer to it as cf, for callforward.
One exception is that in Express, not calling next() is actually a problem because it may leave a network connection open until timeout, thus holding up precious resources on a potentially busy server.
On the front-end we don't have the same rush to release reactive streams asap, so not calling the next function in a chain at all is perfectly fine.

Play!

Click the box below to give imperative streams a go in a frontend/UI context. Are you able to express a UI problem more easily than you would with React, Angular, Vue or Svelte? Drop a link below.

You want to see more?

There is a growing collection of examples using Callforwards where you can get some inspiration and decide whether this is the thing for you.


Lastly, if you like what you've seen you may want to express your appreciation by leaving a Github ⭐ Star so we can continue evolving it for you!


Learn More

Top comments (0)