Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Observables (Rx.js) compare to ES2015 generators?

As far as I understand, following are the techniques to solve asynchronous programming workflows:

  1. Callbacks (CSP)
  2. Promises

Newer approaches:

  1. Rx.js Observables (or mostjs, bacon.js, xstream etc)
  2. ES6 generators
  3. Async/Await

We are now moving away from callbacks & promises to these newer approaches. What I understand currently is - Async/Await is more like a cleaner abstraction on top of ES2015 generators.

What I am not able to understand is the conceptual difference between Observables and Generators. I have used both extensively and have no trouble in using them.

What confuses me is the use case for Observables and Generators. I have come to conclusion that, in the end, they are addressing the same problem - asynchronicity. Only potential difference I see is generators inherently provide imperative semantics to code while Observables using Rxjs seem to provide reactive paradigm. But is that it?

Should that be the criteria to choose between Observable and Generator? What are the pros and cons.

Am I missing the big picture?

Also with Observable eventually making into future Ecmascript, are Promises (with cancelable-token)/Observable/Generators going to compete with each other?

like image 621
Harshal Patil Avatar asked Dec 27 '16 16:12

Harshal Patil


People also ask

Are observables generators?

Observable uses generators to represent values that change over time. Generators enable interaction, animation, realtime data streaming, and all the other exciting, dynamic capabilities of Observable notebooks. The simplest generator is a cell that yields a single value.

What is RX JS used for?

RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code.

What are observables JavaScript?

Observable JavaScript represents a progressive way of handling events, async the activity, and multiple values in JavaScript. These observables are just the functions that throw values and Objects known as observers subscribe to such values that define the callback functions such as error(), next() and complete().


2 Answers

Observables push changes, and hence the observable, not the function reacting to it, is in control. Generators on the other hand require you to pull values out of them. So the function that will react to the new value determines when it is ready for a new value.

I had trouble with backpressure using observables, but with generators, you can let values out as slowly as you want.

Edit: the last question. Promises are just observables that only emit once, so I don't think they will compete with each other. I think the real battle will be async/await vs observables, and async/await has a head start, and is already in C# (and now Node.js). But observables have that sweet FRP feel, and functional programing is super cool, so I think they will both end up with a good chunk of mindshare.

Edit2: André Staltz, author of Cycle.js and xstream, and contributor to Rx.js, wrote a great article on how generators and Observables relate (on 2018-01-31). In particular, he shows how they both inherit from a common base class.

And now a consumer can be a Listener (“observer”) or a Puller, it’s up to the consumer whether it will pull the producer or not. And the producer can be a Listenable (“observable”) or a Pullable (“iterable”), it’s up to the producer whether it sends data proactively or only on demand. As you can see, both consumer and producer are simple functions of the same type:

(num, payload) => void

So any operator that we build will work for both reactive programming or iterable programming, simply because the line between those two modes gets blurred and it’s not anymore about observables versus iterables, it’s just about transformations of data between producer and consumer.

I recommend reading it [link]. The article introduces "Callbags", a spec for callbacks used for reactive and iterable programming. He implements that spec to make a tiny library for both iterable and reactive programming. To entice you to read the article and check out the library, here are some examples from the 7kb lib based on the spec he introduces:

Reactive programming example

Pick the first 5 odd numbers from a clock that ticks every second, then start observing them:

const {forEach, interval, map, filter, take, pipe} = require('callbag-basics');  pipe(   interval(1000),   map(x => x + 1),   filter(x => x % 2),   take(5),   forEach(x => console.log(x)) );  // 1 // 3 // 5 // 7 // 9 

Iterable programming example

From a range of numbers, pick 5 of them and divide them by 4, then start pulling those one by one:

const {forEach, fromIter, take, map, pipe} = require('callbag-basics');  function* range(from, to) {   let i = from;   while (i <= to) {     yield i;     i++;   } }  pipe(   fromIter(range(40, 99)), // 40, 41, 42, 43, 44, 45, 46, ...   take(5), // 40, 41, 42, 43, 44   map(x => x / 4), // 10, 10.25, 10.5, 10.75, 11   forEach(x => console.log(x)) );  // 10 // 10.25 // 10.5 // 10.75 // 11 
like image 103
Sam H. Avatar answered Oct 07 '22 21:10

Sam H.


You can consider the rxjs observables as asynchronous generators i.e. generators yielding promises. Just because the content is not guaranteed to be ready at the time we call .next (in opposition to regular generators)

  • The subscriber will permanently consume into an infinite loop the generator’s content (calling .next)
  • Wait on the returned promise to be resolved (or revoked) to do what you want
  • The observable (made with an async generator) will complete on the generators return.

More reading

asynchronous Iterators proposal

like image 39
Flavien Volken Avatar answered Oct 07 '22 23:10

Flavien Volken