03 March 2015

The Reason for Promises

General purpose programming follows a predictable control flow. When asynchronous code is introduced into our code base, the predictable nature of our code bases control flow is interrupted. This interruption makes our codebase more difficult to read and thus more difficult to maintain. If the project requires us to nest asynchrnous operations then it is easy to fall into the depths of callback hell, at which point the potential for both syntactic and semantic programming errors increases dramatically.

At last, there is hope: Promises provide us a way to mimic the predictable control flow of classical synchronous programming, while getting the benefits of actually performing asynchronous operations under the hood. At it's core a promise is essentially an object which represents a value that is not known yet.

All i/o in Javascript is asynchronous by default. Promises are a means of handling asynchronous i/o in a pseudo-synchronous format. Using promises gives the illusion of seamless and smooth control flow while getting the benefits of having non-blocking i/o.

Benefits and Mechanics of Promises

Promises are chainable which results in a predictable control flow. Promises are chainable because under the hood every method on the Promise prototype returns a promise object. The ability of promises to chain significantly increases code readability and therefore also significantly increases code maintainability. This translates to less time debugging and higher efficiency.

The promise accomplishes asynchronicity by maintaining an internal state which represents whether the promise has been fulfilled or not. The creation of a promise represents the initiation of an asynchronous i/o operation. During the initial stage of creating a promise prior to completing the i/o operation, the promises internal state is set to 'pending'. The internal state of the promise will be 'pending' until the i/o operation completes and it receives the value from the completion of the i/o operation.

When the io operation is complete, the promises internal state can change to either being 'fulfilled' or 'rejected'- depending on the results that the io operation returned. Once the promises internal state is no longer pending, any handlers will be activated that were passed to the promise object will be activated.

If the promises state switched from pending to fulfilled, then a success handler will be activated. If the promises state switched from pending to rejected, then the promises failure handler will be activated. The most simple and commonly used mechanism for setting success and failure handles is the then method.

Conclusion

There are a lot of articles on the internet about how the internals of promises work. But most use cases of promises do not require you to understand their internals.This guide was meant to be a primer for most common uses cases of promises as seen in popular libraries and APIs. I wanted to cover just the very basics in terms of methods because I feel like most articles on promises are more about architecture rather than purpose. For more detailed information as to how Promises are archetectured checkout Promises In Detail.