I've become a fan of functional programming in recent times (even though I still don't know much about it). Over time, I've developed a habit when working with Promises in JavaScript. I try to construct my code so it ends up reading like this:
let tweetsToAttendTo = fetchTweets()
.then(removeDuplicates)
.then(removeTweetsIveRepliedTo)
.then(fetchRelevantTweets);
This means I'm using then
not only to control flow but also to pipe output of one function to the input of another (thereby creating a pipeline). I find that this pattern makes the code easier to read and reason about, and gets rid of unnecessary filler like the arrow function and extra variable in the following:
fetchTweets()
.then(tweets => removeDuplicates(tweets));
Be careful though! There are a few things you must know when using this pattern:
- Applying this method depends on the result of the previous function being the input to the next function
- Be careful when using object methods. For instance, the following two snippets of code aren't the same thing:
getModels().then(r => manager.applyFilters(r))
// any calls to `this` in `manager.applyFilters` will return undefined
getModels().then(manager.applyFilters)
Ultimately, don't force it. I use this often, but if it just isn't working (output of F1 isn't input of F2, F2 behaves differently, I need to do special error handling), I let it go. Remember, no silver bullets!
Top comments (13)
The cool thing about Promises is that the
then
method, when used this way, is just like themap
function. It has the same abstract type signature. This makes Promises behave like any otherfunctor
, which means that this method respects composition. Therefore,is the same thing as
Yes, I was thinking that as well. When chaining a sequence of maps, it's better to only map once using a composition of functions.
I'm curious as to why you think it's better to "map once". I personally prefer using "then" repeatedly, because it might take a while for people who aren't familiar with functional programming to grab the concept of piping.
YES! I wish more people started to use similar patterns to this usage, but I still see a lot of deferreds and new Promise() for standard promise usage
Quite a good read Shalvah A!
as a side note:
I remember finally looking at the light with promises after reading several articles, but the one which clicked on me was this
pouchdb.com/2015/05/18/we-have-a-p...
In it includes one example of your usage, which in turn is part of a quiz in promises, ultra recommended lecture if someone doesn't understand promises
@shalvah this article is fantastic! I've been exploring the ergonomics of the pattern (particularly around promises) for a little while now... I wrote up an example-rich github project to outline the refactor process: github.com/justsml/escape-from-cal...
@Angel, that pouchdb article is amazing, I make all my students read it :D
The only issue I see here is that
promise
is always asynchronous and usingthen
for function chaining might compromise shared data.I'm not sure I understand you. Could you give an example of what you mean by "compromising shared data"?
I mean that each time you chain a function using
then
that function is added to the queue which means that it will wait for at least a tick to be called, my only concern is if during that tick a variable, that one of the callbacks relies on, is modified. Maybe is not a pressing matter, just a concern I have.Nice post tho.
@Pichardo Promises resolve only once, and their value is immutable. And in a functional promise chains each step results in a read-only state.
I've done a couple of functions like this, but still I haven't solved the problems of
.catch
blocks in there to handle specific errors during execution. But the problem would be when you need to exit the chain if an error occurs midway through. In such a case, I don't recommend using this approach, as that would lead to a lot of crazyyyy code. For uncaught errors, the stack trace would typically contain the name of the function that failed.I hope I've addressed your concerns. Did I miss something?
It's called tacit programming or point free. I love doing it too
Right. I recall seeing that in a book on FP. Limiting the number of points.