While it had a good run and indeed solved a problem I was having with a huge project, I’ve been using Promises long enough now to realize there are plenty of ways to handle my use case with Promises if implemented correctly. It really just comes down breaking down your promises into operations that are as small as possible and not being afraid to nest Promises just a little bit when control flow necessitates it.
There was also another major thing that turned me off about Promises initially, though I’ve had a change of heart recently. It was about the proper way to cancel Promise chains, since it’s very easy to get stuck in an anti-pattern if you’re not careful in how you write rejected handlers. What I found really helpful is described by the diagram in section 4.2 of this article:
(Read the rest of the article too if you have time, it’s extremely helpful)
The diagram in that section describes the control flow after a promise is rejected, and it looks very much like a literal game of catch where errors are thrown from the left-side of the diagram and caught on the right. What I didn’t quite understand before is how Promises try really hard to not to stay in a failed state, and they sort of “toss” back to the left side of the diagram unless you explicitly throw another exception. I know that might sound weird, but another way to put it is as follows:
Promise chains that land in a rejected handler will always “bounce” back to the next subsequent resolved handler (provided that no additional errors are thrown within the rejected handler, in which case it would move to the next rejected handler)
This is crucial when managing errors, since if you’re not careful you’ll end up from a rejected handler back in your resolve handlers where you really didn’t want to be. The easiest way to avoid the above problem altogether is to only ever have 1 rejected handler in any Promise chain. Remember that catch() is just syntactic sugar for then(undefined, rejectedHandler). So once you understand that much and realize how Promises flow down the resolved side VS the rejected side, things start to make a whole lot more sense.
Maybe at some point I’ll do a more in-depth post about how promises work and how to avoid certain anti-patterns that I ran into. But for now, don’t use PostScriptum.js and grab another library such as Bluebird, RSVP, or even just use straight up ES6 promises.