Below is a module that exposes three functions. Function getA takes no arguments and returns 'a'. Function getB takes the argument 'a' and returns 'b'. Function getC takes two arguments 'a' and 'b' and returns 'c'. From the perspective of client code, getA has no dependencies, getB depends on getA and getC depends on both getA and getB. If the arguments are not as expected a rejected promise is returned.
Composing getA and getB is easy assuming all you care about is 'b'. This is especially true if you use function pointers (you do right?). The code below shows how. And of course err is handled just once.
Composing getA, getB and getC is a bit harder even assuming all you care about is 'c'. If it wasn’t for the depencencies between the functions then we could just use Promise#all and be done with it. But given the dependencies Promise#all won’t cut it. The code below shows how to do it.
Notice, however, that some nesting has crept in and there is a distinct lack of function pointers. What we really want is some function that can wrap getB and getC whilst carrying over the results of each invocation to the next function. The usage of such a carry function is shown below.
The carry function reduces nesting, allows us to use function pointers and gives us to access 'a', 'b' and 'c'. The code below shows how to define it.
It’s worth noting that this isn’t the only way to solve this particular problem. In fact, I spent a lot of time thrashing about before I settled on this as my favourite pattern.