Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

synchronous vs asynchronous sequences in RxJS

I've got a quite basic, I guess, question about the difference between sync and async operators and sequences.

Everything that we deal with in programs might be represented as a sequence. It means I can have both:

  • array of numbers as a sequence. It's something I would traditionally deal with synchronously, e.g. using a reduce function to count a sum or an average. But I need to know all elements in order to calculate it.
  • array of click events. They come asynchronously (in future & I don't know how many and when they come).

Using the common Observable datatype I can perform many operations on different elements, such as merge, zip etc.

The whole idea of RxJS is to treat sequences in an asynchronous manner, so my question is - what is the point of all average, count, max, min, reduce etc operators, which need the sequence to be completed? If I can't add any element into the sequence (asynchronously add element to an array - why not?) so that it re-calculates - why should I use RxJS over Array.prototype.reduce?

In other words - initially I thought that a sequence should always be capable of performing operators on it (whateevr the operators are) also when the sequence is not completed.

like image 549
ducin Avatar asked Aug 19 '16 07:08

ducin


1 Answers

As you already said, Rx will help you with async events. Sure in the case of reduce you could also use the Array method. But you would have to (a) do the whole calculate from the start, when a new value arrives or (b) store the accumulated value and do a single reduce on a new value.

So, if you're using RxJS it will basically do (b) for you. Meaning, that it will store the accumulated value in the observable created by the .reduce method. Whenever a new value comes along (from the producer) it will apply the methods again.

In case of count, max and min: They are actually filter methods. Sure you could implement this with temporary values and some Array methods. But, if you already tried this yourself, it is really cumbersome to implement and deal with async events. You have to store temporary values, ...

RxJS will abstract all the async away for you. The operators you mentioned are just a big toolkit to transform/filter/... incoming things. I would suggest reading this article by Ben Lesh.

The big win with RxJS is that, especially if you're building a UI, you never know when your "async array" (=events) is complete. So you have to do (a) or (b), which is really annoying. RxJS abstracts this behaviour for you, so you can deal with real problems.

About completion

I missed one point you made about a sequence needs to be completed:

That is not true for all the operators. If you subscribe to the Observable + operator chain you'll always get the current (=last) value produced by the observable. If a new value is pushed through the pipeline the current value will be updated and all subscribers will be notified.

Example

Here is a very very simple example that in my opinion shows why RxJS is such a huge improvement over the "old way of doing things": http://jsbin.com/suqila/1/edit?js,output

In the non-RxJS you always have to store the state and introduce a side effect in your method. With RxJS you can remove the side effect which makes code much easier to reason about.

Sync vs. async

In the article I mentioned above Ben Lesh says:

Observables are usually async.

What he means by this is that you're usually using observables to cope problems that are async, autocomplete is a very popular example. Rarely you can also use synchronous Observables. Observable.of([1,2,3]) is synchronous for example.

This might be confusing at first, but in reality it doesn't really matter. Observables are lazy/push-based. Meaning, they do nothing until they get pushed a new value from their producer and/or someone subscribed to them (depending if they're hot or cold). But it depends on the producer if the process is synchronous or asynchronous.

Same is true for the operators. They are functions that take a source observable and returns a new observable that will subscribe to that source observable when you subscribe to it. That's pretty much it. They execute when a new value is pushed through the operator chain.

like image 170
Sebastian Sebald Avatar answered Nov 14 '22 12:11

Sebastian Sebald