This is crucial to understand! Online materials can often be incorrect.
Very short but meaty writeup.
đ Here are 4 Laws of Observables đ
Law 1
âą All Observables are lazy, without exception.
Law 2
âą Observables are either cold, serving a single execution context per subscription in a unicast manner.
âą Or hot, serving one or more subscribers with the same execution context, in a multicast manner.
Law 3
âą Subject is both an Observable and an Observer
âą The Observable part is multicast, but still lazily executed only when the first subscriber comes.
âą The Observer part is the one created eagerly that allows us to call .next() and send data through the Subject;
âą The Observer part does not imply that the execution context of the Observable is 'alive' before the first subscription is made.
Law 4
âą There are stateful Subjects, like BehaviorSubject or ReplySubject, which extend the Observer part.
âą Adding support for holding 1..n previous states, which the Observable part will multicast to potential subscribers.
By reading this, do you think that RxJS is a complex subject (pun intended :D)?
Angular Team announced plans to potentially make RxJS optional in the future.
Would you like to keep RxJS mandatory?
Or optional is the right way to go?
Top comments (17)
I have never used rxjs in a real app.
However, I don't find the arguments for its usefulness very convincing.
The biggest reason is that JavaScript is single-threaded, so there is no data race.
Are there any use cases where rxjs is really helpful?
Here's a link explaining reactive programming: core.lirx.org/docs/documentation/g...
The purpose is to work with async code. JS is single threaded as you said, and this is especially why async (Promise, Observable, EventListener) are so well integrated in the language's APIs as we MUST have a way to order and manage tasks to avoir freezing the main thread.
Reactive programming expresses its full power when mastering it, which is, to be honest, not an easy task, as it it a totally different paradigm. However, it solves a lot of async issues: avoids typical concurrency problems, automatically updated variables, etc...
This is why current front-end frameworks like react, angular, vue, svelte tends to add more and more reactivity (useSignal, useState, signal, etc...)
Thank you for your detailed answer.
However, I think my question was a bit lacking.
Rxjs has a relatively steep learning curve due to its large number of operators and paradigm differences.
The
rxjs.umd.min.js
file on npm is 88kb, which is even larger than jQuery.Even if we ignore these drawbacks and don't convert events to streams, JavaScript can easily implement things like ensuring the order of asynchronous logic, debouncing, and throttling.
Therefore, I'm curious if there are any cases where RxJS is really useful.
For example, a few months ago, I searched for "Rxjs Complex example" on Google and found a source code with the same title.
However, that example could be easily implemented without RxJS, as follows.
Using async-lube instead of Rx.js
I think the first step is to view the distinction between the different paradigms. Usually developers learn imperative programming. Here we speak of something completely different: reactive programming. More paradigms exist like functional programming but it's another topic. You way somehow compare it with the introduction of Promises which changed many things.
RxJs is a framework to code in reactive programming, but you may use another. Somehow, has I said, svelte or react provide tools too to use reactive programming.
Now let's explain what reactive programming solves: applications with very complex state, and very complex stream of data. When you'll work with applications having 100k lines or more, it becomes critical to have a good engine to manage a perfect consistency.
Reactive programming through Stores are a solution, as well as RxJs.
In such an application you'll encounter a lot of values (variables) depending on others (a variable computed from another + taking some data from two different API calls fo example). Here we speak about: stream aggregation, stream switching, and dynamic computed values, but many more complex use cases exist.
With reactive programming, you'll be sure to have always the correct values, automatically updated, with a perfect consistency.
About the size now: yes the lib is not light, BUT, you'll be able to do the same thing in 5-10 lines of code instead of 50+ lines of code in imperative programming, so for big applications as well as maintenance this makes a big difference.
Finally, about complex examples, I don't think it can exist. The purpose of an example is to be understandable by everyone. But complex RxJs examples would require high understanding of the framework, so it won't be relevant. Maybe, you could use chatgpt to interact with it and give you examples with explanations or take a look at the Wikipedia page en.m.wikipedia.org/wiki/Reactive_p...
However, if you want some simple example, I've created a website giving you an usecase
core.lirx.org/docs/documentation/e... . Take a look, I hoped I helped you, and any feedback is welcome đ€
Going really reactive in Angular, for example, is hard to think without RxJs... I've used it EXTENSIVELY over there and now I couldn't think of working any other way in Angular... Well, at least until Signals become prod ready...
Also, RxJs becomes easier to use and understand when you get to know the usual recipes for the usual most common scenarios, like for an autocomplete, where you know you have to pipe debounceTime, distinctUntilChanges, switchMap most of the times, and with just a couple lines of code whereas in react or others is a lot more code, much more error prone and harder to maintain.
Yes, steep curve, but once you're in, it's hard to leave.
Good explanations, btw.
I liked the examples you provided.
I have my doubts about the usefulness of RxJS, but it doesn't seem to matter that the library used in the example is
@lirx/core
.My point is not about reactive vs imperative.
It's about streams vs events.
For example, the example you provided with lirx can be written as follows
The naive example shows that reactive can be applied to local and date without additional learning curve, and change the value with
onchage
andsetInterval
event, respectively.It's true, we can do everything we need with vanilla JS. However, building larger and larger applications you'll want to structure your code in DRY patterns, and add flexibility to calling your function with different parameters, and before long you'll discover that you've just reinvented rxjs or some other library. I think many of our performance and usability benchmarks suffer from this requirement that we show a comparison between languages/libs/frameworks by building a simple TODO list app with each.
There's also another dimension to our argument here. We are all human beings striving to understand the universe and/or build wonders. And while we can build a lot of glorious things with a hammer and a chisel, we only level up in our experience and understanding when we change our perspective. Using a different mental model is hard, that's why we tend to resist changing our ways. But it is exactly doing the same thing with different tools and different restrictions that really fuels our personal growth.
I would suggest googling differently too:
@artxe2 Well, actually it misses two points:
setInterval
on the 'change' EventListener, when you want to dispose of them (ex: when destroying the output element). Now, in real applications, you'll usually create dozens of async tasks per component (fetching an api, updating data, listening to user events, etc...). So, it will quickly become a mess, is error prone, hard to maintain, and often the source of memory leaks. With observable, it's all done in one call => the returned unsubscribe function.Here we speak about big and complex applications that need robustesses and consistency. For example: the drive or mail interfaces of google. Having a bug free interface with consistently fresh data and no memory leak is critical in many businesses.
Now, fundamentally, Observables are just... functions. The libraries (rxjs or lirx/core) simply provide helpers to combine and pipe them, but you may just create your own in a few lines of code. Somehow, this is like
lodash
but for reactive programming.Finally, if you prefer a "sync style" you can do the same with
@lirx/core
signals.Please define real app. How many lines of code, trying to achieve what overall.
How do you use the HTTP API, the router one and how to you broadcast changes in your app?
JavaScript being single threaded doesn't prevent race conditions in your code. JavaScript is single thread and therefore requires you to deal with queues of events, which can definitely lead to race conditions.
and now try
When you need to deal with several asynchronous sources of data. Which, depending on the complexity of you app can happen quite a lot.
If you want a concrete example, I did write an implementation of a split flap display and explained everything in that blog post: dev.to/maxime1992/rxjs-advanced-ch...
If we summarise how the asynchronous bits are handled, here's how small it can be:
11 lines. To manage all the complexity of that time based, asynchronous machinery. RxJS is not helpful, it's just necessary. If you disagree, please try to implement that exact behavior without using RxJS. If it's has concise, readable and understandable as the above, I'll reconsider my answer.
I have read the attached article.
I tried writing the examples in the article without Rx.js, and I didn't find them too difficult.
However, I think Rx.js would be useful in cases where multiple events are connected to a single flow in a complex dependency chain. I haven't come across such a case yet, though.
Woups yeah, I shared the wrong article that was the one purely rxjs, which is less interactive (can't change the text on the fly). I wanted to share this one: dev.to/maxime1992/build-a-reactive...
I guess the difficulty here would be for you to cancel promises, if you've got some time feel free to give it another go and while the text is being updated, try to type in some new text while making sure the split flap display doesn't start from scratch but rather continue from where it was.
For some reason, an error occurs in the example you attached.
However, I have tried to add a simple function to receive user input to the previous implementation.
Because the requirements are specific, it was possible to implement it simply by adding a conditional statement to the loop, and the complexity did not increase in the asynchronous part.
You nailed there, man. You can say it louder but not clearer đđŒđđŒđđŒđđŒ
A
BehaviorSubject
reading this post:If you havenât used rxjs in an angular app, thatâs a pretty simple, non-interactive app.
Or a hard-to-maintain one written in the imperative way... đ
The big merit of Angular having made known Typescript and RxJs to the Web World.
Typescript and RxJs are so deep rooted in science that will outlive any Web Framework