Promises, Promises Pt. 3
Composing in ES6
I don’t know what your familiarity level is with functional programming, and I’m not planning to go too far into it. I’m currently taking a specialization on the subject on Coursera, but if you’re totally new to the concept, I would really recommend the YouTube channel Fun Fun Function by Mattias Petter Johansson (a.k.a. mpj). He breaks down the basics of functional programming reeeeeeaally well. For now we’re going to do what functional programming does best: compose.
forEach iterates through the array and does something with each value.
This is very imperative, very performative. Take the value, do something with it.
map is little more functional, more informative. it takes in a transformer function that transforms a value into a different kind of value, and returns a new array with all the values passed through that transformer function.
In this case, I wasn’t super transparent about the
catch functions. In the last post we treated them like the
then can also act like the Array’s
map function, transforming the promise. Take a look below:
So we can use
then like a
map function! What about
catch? Can we transform the error? Let’s take our
luckyPromise from before and switch it, so that when it has a value, that becomes the error, and when it gets an error, that’s valid.
But wait, there’s more! There’s a third function that
then acts similar to:
flatMap function. Seriously, I don’t know why it’s not there. But the idea is that
flatMap would take in a function that takes in one of the array values and return a new array. Then
flatMap would return a new array that concatenated all those values together. Instead of returning an array of arrays, it just returns an array of values.
It may seem a little weird to talk about a function that doesn’t exist, but it does in lots of other libraries like this. In fact, it’s a pretty integral part of the definition of a monad which is this big thing in the functional world. Most other languages with functional collection wrangling have it, like LINQ (though they call it
SelectMany). Anyway, my point is this: if Promises had a function like that, it would take in a function that returns a promise, but instead of returning a promise of a promise of a value, it just returns a promise of that value. Well,
catch do this implicitly! If the return value of the function is a promise, it just shortens that down.
That’s right! Your first instinct is that
composedVal should be the
internalPromise, since that’s what’s returned from that function, but promises see that you’re returning a promise and compose a
flatMap instead of a regular
map. One of the great parts of that is that you can use this to compose promises, or even provide a fallback promise.
We can see how to use
then to perform some of this combining. There are two more functions from the Promise API that I want to point out:
Promise.all is a great function that turns an Array of promises into a promise of an Array. It resolves when all of those promises have resolved, or rejects as soon as any of them rejects. Let’s take my nacho example and say that I have sent out two roommates, one for chips and one for cheese.
I will be honest that I have not used this one in production yet, but
Promise.race is the “logical or” to
Promise.all’s “logical and”. If all the items reject, this will reject with an array of their reasons, but if any of the values resolves, this will resolve.
I usually found that, if I requested the promise, I probably need it, but this might be a good way of prioritizing content based on when it came back while waiting for the other stuff to show.
So, this concludes the ES6 Edition of Promises. In the following post, I’ll do the same thing, but for Angular.js syntax, then we’ll talk about some real world problems I had and how I composed promises to solve them.