Reactive Programming Pt. 2 — Asynchronous Time!

A previous post of mine introduced the concept of reactive programming via the excellent RxJS library. The example was a name shortener — a series of RxJS operations that shortened a name from something like “Christopher Robert Evans” to “C Evans”. That’s cool and all, but programming should be practical, down to earth… so let’s have a superhero punch villains and rescue orphans.

With reactive programming, of course.

But First, a Promise

That is capital P promise, as in the ES2015 Javascript standard object. Javascript needed some way to execute code after a particular action was done outside the main “thread”. As time proved, that was an awful way to do it:

That is just a mess, and that’s not even the worst part: imagine building exception handling into that!

Luckily, the Javascript standard has been amended with a feature called Promises (supported on all browsers except IE) which let you run some code asynchronously (such as sending a HTTP request or waiting 5 seconds) while providing a sane interface for interacting with the outcome:

Creating a Promise, you give it a function that takes two callbacks as arguments. That function will get run asynchronously, and you can report its return value via one of the callbacks, and any error data via the other. The Promise object then can accept any number of .then() or .catch() calls to register behavior that should trigger on success or on failure of that Promise. Since each call to those functions itself returns a Promise, it can be chained forever. It’s cool!

But do be sure to actually follow through on promises and not leave them hanging forever

So, using Promises, let’s rewrite that horrible horrible code from earlier:

Much better, right? We started off the promise chain with a .resolve , which just creates a Promise returning a value immediately (so we have a starting point).

Reading the code, you can see it’s even descriptive: take the words, then map them into promises based on each word, then wait for all promises to be done, then join the resulting words with a space and print it out. Also note: this code is much faster! Since all the promises are created (and launched) at the same time, the 1 second of waiting in the four calls of slowlyUpperCase gets done in parallel.

Back to punching villains and rescuing orphans

Captain America is the right guy for the job. However, this being a programming blog, we need to represent Cap’s heroic actions in a more plain form, so let’s just make a couple of Javascript functions describing what his life is like:

Let’s try doing some heroic work:

That’s not the right reaction… Let’s try again, this time with Promises. Remember that Cap is still human; he can’t rescue all the villains and orphans at the same time. He can punch a villain and rescue an orphan at the same time, though — he is a superhero.

We have two promise chains: one for punching villains one by one, and the other for rescuing orphans. We then wait for them to be done (in parallel), and print a done message. That’s much worthier of Cap, but we have a problem: what if the villains just keep coming and orphans keep needing rescuing? What if, in fact, it’s constant streams of villains and orphans for Cap to handle? Can he react to it?

Enter our friend, Subject from RxJS! RxJS is in part inspired by the way Promises work. That is why an Observable is essentially just a Promise that can be “fulfilled” multiple times*. So with that in mind, let’s redo our Promise code to use Observables instead:

Yay! The concatMap operator is one of a few operators (such as flatMap and switchMap) that can combine multiple Observables into one. That’s what we’re doing here, since the punch/rescue functions create new Observables that we need to chain. Namely, concatMap takes the results and chains them end to end, waiting for each chain to complete before commencing the next one. Of course, being asynchronous, both of the chains operate independently, so Cap can punch villains and rescue orphans at the same time.

You might have noticed, though, that that code doesn’t actually do anything. That’s intended. Like Captain America being prepared to dash into action, it’s waiting for values to enter villains$ and orphans$. It could be like this:

for (var villain of ['Red Skull', 'Loki', 'Winter Soldier']) {
villains$.next(villain);
}

Or like this (using jQuery XHR as Promise):

$.ajax('http://hydra.evil/kidnap/victims?parents=0&ageLT=18')
.then(data => JSON.parse(data))
.then(victims => victims.forEach(v => orphans$.next(v)));

Or even like this (using an Angular 2 template):

<label for="evilInput">
Who is attacking NYC today?
<input #evilInput id="evilInput" type="text" />
</label>
<button (click)="orphans$.next(evilInput.value)"> Punch! </button>

*Promises and Observables have very different flow (push vs pull respectively) so they are not quite equivalents, but that’s a topic for another time. For today’s post, they’re close enough.