DEV Community

Cover image for Implementing "Suspense" with a simple Observable
Dario Mannu
Dario Mannu

Posted on • Edited on

Implementing "Suspense" with a simple Observable

Some frameworks tend to overcomplicate stuff that's otherwise trivial.

We want to render some text whilst another process is pending, then display the results. Some people call this "Suspense".

We can implement it as a simple stream that emits a placeholder initially and the final result when it's available.

A BehaviorSubject from rxjs is all you need to get started.

import { BehaviorSubject, switchMap } from 'rxjs';
import { rml } from 'rimmel';

const getData = () => fetch('/api').then(r=>r.text());

const suspended = new BehaviorSubject('Loading...').pipe(
    switchMap(data)
);

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

Try it yourself on Stackblitz

The reason why

So, why should you use this, instead of the alternatives?

You could use Angular, but you'd have to convert this to a Signal. You could use React, but you'd need some adapter library such as react-rxjs. You could use Vue.js, but there you have to subscribe to the stream, update a signal and use that.

Also, with most of these you'll have to manually unsubscribe from your streams to avoid memory leaks and clean up after yourself.
None of these are very practical.

Rimmel.js is the only UI library that makes it possible to use reactive streams directly in your templates, simplifying UI development considerably.

It also simplifies the use of Observables, traditionally considered a particularly challenging endeavour.

If RxJS is the best library for reactive streams, Rimmel is the best UI library for RxJS. Try it out now for a totally new development experience.

If you like this approach please don't forget to leave a Star in Github ⭐ so we can continue evolving it!

Learn More

Top comments (9)

Collapse
 
nevodavid profile image
Nevo David

Pretty cool honestly - keeping stuff this simple makes me wanna mess with it just to see how lean it feels in practice.

Collapse
 
dariomannu profile image
Dario Mannu

Please, do and let me know how are you finding it. I have a few Collections with over 200 examples based on this keeping stuff this simple idea.

Collapse
 
werliton profile image
Werliton Silva

I agree.

Collapse
 
werliton profile image
Werliton Silva

In your opinion, what is the difference between React suspense and this one in the post?

Collapse
 
dariomannu profile image
Dario Mannu

React's Suspense only does "suspense" and only for React.

BehaviorSubject is a general-purpose state management genius invention, part of RxJS. It can be used to solve any state management problem efficiently, can be used for suspense as in the example above and to solve any problem that can be modelled as a stream (data in, optional transformations, data out), which means really a lot of use cases.

RxJS has some learning curve but what it gives you is the general-purpose thing, so instead of having to use a suspense library, a local state management primitive, a global state management library, a saga library, etc, you always use the same couple of streams and operators to achieve all these with a fraction of the code. Also, Observables are on their way to become a web standard and are already natively supported in Chrome.

I'll publish a new getting started tutorial on this topic shortly. Stay tuned if interested.

Collapse
 
werliton profile image
Werliton Silva

Damn, that was solid, dude. Huge thanks for breaking it down. I’m hyped for the next ones. Much appreciated!

Collapse
 
dotallio profile image
Dotallio

Love how straightforward this is compared to all the boilerplate in React or Angular. Have you hit any real limitations with this pattern when building bigger apps?

Collapse
 
dariomannu profile image
Dario Mannu

Limitations, not really, just a bit of learning curve and a discovery journey.
The reason is probably the strong theoretical basis to the scalability of this concept. Without getting lost in cathegory theory and abstract algebra, the short summary is this:

  • Reactive Streams (e.g.: RxJS) are Monads
  • Components are Monads, too (Component = (...args) => TEMPLATE(...args))

Using both you can formulate any problem reusing the same few building blocks (map, reduce, filter, etc).

This means the larger the app, the more it will benefit from this stream-oriented paradigm.
Lots of enterprise React/Angular applications end up in bundles that weigh several MB. Using only reacive streams and components you can hardly go above 100-200K.

Performance also benefits greatly: there's no Virtual DOM or any complicated Change Detection or Re-rendering: since everything is a reactive stream, DOM Events feed them directly and the output goes back to the DOM in a straightforward path you have full control over.

Collapse
 
werliton profile image
Werliton Silva

Cool!