Hacker News new | ask | show | jobs
by shados 3238 days ago
The main point is correct.

But observables are very different from promises at the core. Not only are they cached, but they're also eagers, while observables are not. The very minimum implementation of an observable is just a few lines of code. Promises...are much more complex. So I'm not sure how reusing operators between the two efficiently would work.

So yeah, just use observables. Most people think observables are a more complex, higher level abstraction with promises being the primitive, simple one. It isn't true though. Observables are much, MUCH simpler, and are perfectly suited to doing everything promises do, but better (lazy, optionally cached async primitive is way better).

1 comments

You can make any observable "cached" in RxJS by subscribing it to a ReplaySubject or by calling .publishReplay(N).refCount() on them. So observables can be cached or uncached, and the cache length can be specified (N parameter). They can also be eager or lazy; that is the hot/cold lingo in RxJS world (or unicast/multicast).

I repeat my claim: Observables (at least as implemented by RxJS) are a superset of (cancelable-)promises. Superset means, they can do everything the exact same way as promises, and a lot more.

Yeah I know. I explained myself poorly. The observable itself is lazy and cold. Wrappers functions, observers (like subjects) and operators can add a higher level abstraction to change that. It's easy to make lazy into eager and cold into hot, of course, but the observable itself is cold/lazy.

Observables can do everything promises can do, but the construct itself, while more flexible, is significantly simpler. Like, -way- simpler. And a lot of what they do and how they do it comes from how they're implemented at the very base (essentially a generic observer pattern). Building observables on top of something else would add tons of overhead/complexity for no reason.

The observable needs to be the lowest level piece and we build the rest on top, not the other way around. That is counter intuitive since they can do so much more: the abstractions on top are more like specializations of the low level construct.

No disagreement here. Rx observables are strictly more powerful than promises/futures/streams.

But why start with the superset? I don't think it's good design. Consider the perspective of a language designer. You want to start with primitives that are as simple as possible while satisfying a vast number of real use cases. One-short async primitives are an important intermediary step towards observables, it shouldn't be skipped. Observables should be implemented in terms of these.

This layered design gets you a smaller cognitive cost of entry (promises are hard enough as it is!) and higher efficiency for the vast number of cases that don't need stream-like functionality.

On top of that, one-shot primitives are conceptually compatible with blocking expressions in coroutines such as async/await, whereas streams are not.

I don't get it when people shoot for fat primitives that do it all.