Learning Cycle.js — Two months later

Felipe Lima
3 min readMay 9, 2016

--

A couple months ago I decided to (once again) jump into the web development bandwagon, motivated by curiosity and "nerdiness". I've been neck deep on Android only for quite a while now, so it was about time for me to learn something different. Cycle.js caught my attention as a "functional and reactive framework for the web", and my recent growing interest into Reactive Programming, more specifically, RxJava, made me want to try it.

I've been a long time fan of functional programming. It always fascinated me how you could compose complex operations out of simpler constructs, while at the same time avoiding lots of variables, state management and housekeeping, that is, all that stuff that makes your imperative code become completely messy and unreadable. However, Haskell was pretty hard to learn, understand or simply find any real life usage. Scala was another option, but I failed to pursue it, not sure why. Javascript is not functional, but lends itself pretty decently to it, plus the new ES6 features made it a lot more enjoying to work with it.

Getting the basics right wasn't that hard. Having prior RxJava experience was essential for me, in order to grasp how the streams work, so getting a simple Cycle.js app running was a lot easier than I initially expected. Nevertheless, as usual, things get a lot more complicated as your app/website/system/codebase runs bigger and bigger. As I went through it, all I could think about was André Stalz's excellent tweet about learning:

Right on

Disclaimer: The code mentioned here and where I've experimented with this stuff is open source, so you can learn from my mistakes on GitHub with the Robert Hood web app. It is a web interface for Robinhood accounts.

For any non-trivial app, you're most likely to have to mix streams together (at least HTTP, DOM and state). For example, you'll probably need your app state to be used to populate your views (DOM). Also, you'll for sure need to make some http requests to an API and use the responses to initialize your state. Quickly your app will become a graph of complex interactions between each individual stream. Seeing how they connect to each other get harder as it grows and being able to "visualize" it is key to understanding how your code works. While I haven't tried it myself yet, I'd recommend drawing boxes and arrows on paper to help visualize that graph.

Another side effect of mixing streams together is that every time an Observer subscribes to a stream, it causes that stream to emit events, that is, it "runs" it. Your Cycle.js main() function code is supposed to run only once in order to build the graph, however, multiple Observers will cause stream code to be executed N times, where N is the number of Observers subscribed to that stream. That happens because most RxJS Observables are cold by default. André explains it better than me:

RxJS Observables are generally cold. This means that two different calls to subscribe() will generate two separate side effect free executions of the Observable. Hot, on the other hand, is when different calls to subscribe() may share the same execution of the Observable.

Understanding the difference between hot and cold Observables was key for me to be able to scale my code and was by far the biggest learning challenge I've faced during these two months.

As a result of that, you'll have to carefully spread calls to share() throughout your code wherever there is a stream being shared. This effectively turns your cold Observable into a hot one.

Happily I've literally just learned while writing this post that Andre Stalz is now working on a new reactive stream library tailored for Cycle.js called xstream. I believe that will greatly simplify the code and reduce the barriers for people aiming to Cycle.js.

Conclusion

Even though Cycle.js, RxJS or Reactive and Functional programming in general have a pretty steep learning curve, I still firmly believe that these tools and frameworks provide a much stronger abstraction and paradigm than the ones we're usually more familiar with (imperative and object-oriented). Being able to restrict and control side effects is key to building flexible, loosely-coupled and scalable systems. Cycle.js still demonstrates me that it has a lot of potential and with the introduction of xstream it might become even easier and enjoyable to work with.

--

--