Promise is an specification to handle async calls. There are several ways to solve this problem a very popular solution is using callback arguments. In this article I will introduce promises and do a shallow comparison of both solutions.
The problem
Imagine you need to request some data from a server and once you have the response, you will format this data and display into the screen.
For the sake of simplicity and abstraction, let’s consider: - The method “asyncRequest()” that will request some data from an endpoint. - Only success case for now, later on we add error handling.
Using callback
1 2 3 |
|
Using promises
1 2 3 |
|
So what?
At first glance it’s not a big change, but looking more carefully in fact what is happening on the promise example is that the asyncRequest is not triggering the callback function instead it is returning an object that implements the method then, and this object (which is called promise) will trigger once it’s fullfilled.
Let’s keep the baby steps and not dive too fast. So now that we have the response we need to validade this data sending this to another service, to do so we will call asynValidation(data).
Using callback
1 2 3 4 5 6 |
|
Using promises
1 2 3 4 |
|
Whaaaaaaat?
Now we are talking, so the benefit of delegating the event triggering is that you can build a chain of execution, and whatever asycnRequest return will be passed as argument to asyncValidation.
To better undestanding, let’s think on a possible implementation of the asyncRequest method.
Using callback
Ok, this is such a bummer, but I don’t want to mess up with any HTTP API, instead I will use a setTimeout to simulate an async process.
1 2 3 4 5 6 7 8 |
|
Using promises
The example below the variable q is a promise library, I will get into it below.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Enlightening
The variable q is the library that implements a promise solution, when called .deferred it will create a promise manager, I know that’s not the best name, but think that this manager owns the promise and also dictated if it will succeed or fail.
Notice that it returns deferred.promise, which is the promise itself. Yet there is no definition of success or fail, it is called pending promise.
Once the timeout executes the deferred will trigger .resolve(response) which is the way to say, this promise succeded, go on with the chain and use this response variable as parameter to the next method.
It means that as soon as the promise is resolved the then method will be invoked and it’s function will be called.
Chaining
Chaining is only possible because the then method also retuns a promise, thats will be triggered automatically once it’s function is done and it’s return value will be carried over to the next function as parameter, so you can do thigs like:
1 2 3 4 5 |
|
Failure handling example
Adding a fail scenario to asyncRequest and asyncValidation.
Using callback
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Refactoring to a little bit:
1 2 3 4 5 6 7 8 9 10 11 |
|
Using promises
1 2 |
|
OR
1 2 3 4 |
|
Shortest conclusion ever
Chaining is a readable and expressive way to write code, I particularly keep using callbacks for very simple cases but when I notice that it requires me to execute one function after other, I go straight to chaining with promises.
Callbacks inside other callback is a problem well known as callback hell this is a good enough reason to give a try for promises.
Also there is much more the then and catch but it depends on the implementation you will use. Another useful method is .finally() as it sounds like will always execute as the last element of the chain.
Links
Hope you have enjoyed and be curious enough to take a look at the promise definition:
And some of it’s implementations:
- Kriskowal q: https://github.com/kriskowal/q
- AngularJS implementation $q: https://docs.angularjs.org/api/ng/service/$q
- More references on: https://promisesaplus.com/implementations
Extra
The original problem presented here is a piece of a general topic named “Communicating Sequential Process”, you can check more if it here https://en.wikipedia.org/wiki/Communicating_sequential_processes and also some other solutions other than promises and callbacks are listed below.