I don’t mean to say promises are not useful. They certainly are useful and they are a tool that I know well. I think you should know them – but I don’t think you should use them as your default for async code.
Why not use promises, by default?
The TL;DR is that promises add another layer of complexity and potential bugs – especially around error handling.
But, I’m not going to elaborate on the complexities much. Nolan Lawson did an excellent job of pointing out the problems with promises, already.
He starts that post with a question, asking you to explain the difference in four uses of a promise.
This, to me, demonstrates the primary reason that I don’t reach for promises by default. There are a lot of potential mistakes to make.
I reach for promises when I see the need.
That need typically arrises in one of the following scenarios:
- I need to wait for multiple async responses before continuing
- I want to cache a response and skip doing the work multiple times
- I want to chain methods together
- Working with async generators
The Promise.all method is great for waiting on multiple async returns. It lets you pass in an array of promises and wait for all of them to complete before firing the callback.
Caching a response is also useful, though there are many ways of doing this (including the memoize function of lodash / underscore, and others).
Chaining methods together can often make existing promises easier to understand and modify, though I don’t typically do this unless I’m already working with promises.
And lastly, the current ES2015 (ES6) generators implementation facilitates better async patterns in our code, but only when we add a small library around the generators.
I still prefer Node.js-style callbacks.
Having spent several years working in Node.js, I’ve grown to like the callback style where an error object is passed in as the first parameter.
This code, in my experience, allows more flexibility while preventing the potential problems of swallowed and lost exceptions, that promises present.
Until we see the async / await syntax from ES(v.whatever) make it into Node and most browsers, I’ll probably continue to reach for the callback style as my go-to for async code. Even when that happens, it will take a long time for this callback style to move to the side (if it ever does) due to shear momentum of existing code.
A promise is a tool you should understand, and use.