I guess you could argue if you had tons of data, but I wouldn't be using a frontend application to implement a distributed queue processing and messaging system...
It’s used a lot more on the front end than on the back end, in my experience. But I really enjoy working with it.
The vast majority of observer pattern use cases are solved a lot more clearly by using async
I know some not bad js developers who use RX a lot and have no idea about `async/await` existence, I even had to explain to couple of them how `async/await` works and what is "imperative code". No joke.
Sure you can do it with imperative programming, without RX. You can also filter an array with a for loop instead of using .filter(), but the latter is often more desirable. Just like the array .filter() method, you have to stop & learn something you already maybe know how to do with a loop, but the benefit is writing less code to do it. Heck you don't even need the loop, you could use goto statements to filter an array.... but there are reasons to work at higher abstraction levels.
Another example is an auto-complete, traditionally each key up event / input event would trigger an ajax request, and requests may finish out of order causing race conditions. RXJS has a way (switchMap I think) to declaratively say "give me the results in the correct order", another operator declaratively says only give me the latest event.
This is not new in any way, big companies like Microsoft & Apple have been doing reactive functional programming since like the 70s, I think. Its just new to Javascript is all. Just like other programming paradigms, its also not the answer for everything, just another tool to use. I believe in Angular 4, all http requests return observable now. Vue.js (v3) will also switch from object.defineProperty to observable pattern. GraphQL subscriptions / Apollo Client uses observables....
An observable is like a promise, but nothing executes until you call .subscribe(), so they are lazy. You can describe what will happen in response to an input event, such as making an ajax request, without actually kicking off any ajax requests until those events happen. This isn't possible with a promise, which starts its async action as soon as its defined.
They can be cancelled before you call .subscribe(), and they are multi-valued. They can finish after emitting multiple values, or even a single value. Or they could finish without emitting any values (think like a promise, but with cancellation)
Also like a promise, it makes composing callback based code simpler.
In the auto-complete example, you can think of the program like a stream. Input events get turned into ajax requests which get turned into stuff displayed on the screen. Its a stream, and RXJS is how you setup the plumbing. Then data flows through that stream at run-time, without having to maintain any state. For a lot of use cases, this will result in more confusing code than doing it imperative. For other use cases, it will eliminate a lot of race conditions & create succinct easy to debug code. Its a trade off. The trade off is a higher learning curve, but the benefit is more declarative async code.
For further info I recommend to lookup Ben Lesh on youtube.
One of the nicer sides of using Rx is that converting from one implementation to the next is usually fairly trivial.