After learning about Observables, I find them quite similar to Node.js streams. Both have a mechanism of notifying the consumer whenever new data arrives, an error occurs or there is no more data (EOF).
I would love to learn about the conceptual/functional differences between the two. Thanks!
Both Observables and node.js's Streams allow you to solve the same underlying problem: asynchronously process a sequence of values. The main difference between the two, I believe, is related to the context that motivated its appearance. That context is reflected in the terminology and API.
On the Observables side you have an extension to EcmaScript that introduces the reactive programming model. It tries to fill the gap between value generation and asynchronicity with the minimalist and composable concepts of
Observer
andObservable
.On node.js and Streams side you wanted to create an interface for the asynchronous and performant processing of network streams and local files. The terminology derives from that initial context and you get
pipe
,chunk
,encoding
,flush
,Duplex
,Buffer
, etc. By having a pragmatic approach that provides explicit support for particular use cases you lose some ability to compose things because it's not as uniform. For example, you usepush
on aReadable
stream andwrite
on aWritable
although, conceptually, you are doing the same thing: publishing a value.So, in practice, if you look at the concepts, and if you use the option
{ objectMode: true }
, you can matchObservable
with theReadable
stream andObserver
with theWritable
stream. You can even create some simple adapters between the two models.You may have noticed that I changed a few names and used the simpler concepts of
Observer
andSubscription
, introduced here, to avoid the overload of reponsibilities done by Observables inGenerator
. Basically, theSubscription
allows you to unsubscribe from theObservable
. Anyway, with the above code you can have apipe
.Compared with
process.stdin.pipe(process.stdout)
, what you have is a way to combine, filter, and transform streams that also works for any other sequence of data. You can achieve it withReadable
,Transform
, andWritable
streams but the API favors subclassing instead of chainingReadable
s and applying functions. On theObservable
model, For example, transforming values corresponds to applying a transformer function to the stream. It does not require a new subtype ofTransform
.The conclusion? It's easy to introduce the reactive model and the
Observable
concept anywhere. It's harder to implement an entire library around that concept. All those little functions need to work together consistently. After all, the ReactiveX project is still going at it. But if you really need to send the file content to the client, deal with encoding, and zip it then the support it's there, in NodeJS, and it works pretty well.