What is JavaScript all about: Promise
JavaScript runs code sequentially in top-down order. Sometimes (which actually happen a lot) we want to run code after function has finish executed or an event has happened means to run the code in an asynchronous way.
Since JavaScript is synchronized language, we need to find a way to run it in an asynchronous way.
To achieve it we use callback functions. a callback function gives us the ability to execute a function/event/action in an asynchronous way.
But wait there is a problem
While callback functions are the way to handle the synchronous problem, callback functions have some downsides such as the pyramid of doom (or the callback hell).
Promise to the rescue
Promises didn’t go mainstream right away. Actually, when the community start to look for ways to handle asynchronous behavior, callback functions were chosen. It is only when jQuery started to implement Promise on their code base (which become popular and widely used) when Promise started to get reputation.
Early implementations of promises began to appear as early as the 1980’s. The use of the word “promise” was coined by Barbara Liskov and Liuba Shrira in 1988.
A promise is an object that may produce a single value some time in the future. It has 3 different states:
- Fulfilled:
resolve()
- Rejected:
reject()
- Pending: not yet fulfilled or rejected — A pending promise can either be fulfilled with a value, or rejected with a reason (error).
Promise constructor
The function passed to new Promise
is called the executor. Its arguments resolve
and reject
are callbacks provided by JavaScript itself. Our code is only inside the executor.
the executor runs automatically and attempts to perform a job. When it is finished with the attempt it calls resolve
if it was successful or reject
if there was an error.

The promise
object returned by the new Promise
constructor has these internal properties:
state
— initially"pending"
, then changes to either"fulfilled"
whenresolve
is called or"rejected"
whenreject
is called.result
— initiallyundefined
, then changes tovalue
whenresolve(value)
called orerror
whenreject(error)
is called.
Successful job — fulfilled promise
When calling the Promise constructor with new Promise()
The executor is called automatically and immediately and receives two arguments resolve
and reject
. Both of them are pre-defined by the JavaScript engine, so we don’t need to create them. We should only call one of them when ready.
After one second of “processing” the executor calls resolve("done")
to produce the result. This changes the state of the promise
object:

Unsuccessful job — rejecting the promise
This time, the job had an error and therefore we rejected the promise and move the promise object to "rejected"
state:

the executor should perform a job (usually something that takes time) and then call
resolve
orreject
to change the state of the corresponding promise object
The properties
state
andresult
of the Promise object are internal. We can’t directly access them. We can use the methods.then
/.catch
/.finally
for that.
then, catch, finally
A Promise object serves as a link between the executor and the consuming functions, which will receive the result or error. Consuming functions can be registered (subscribed) using methods .then
, .catch
and .finally
.
then
then()
takes two arguments, a callback for a success case, and another for the failure case. having both functions are optional, so we can add a callback for the success or failure case only.
The first callback is invoked when the promise is resolved. The second callback is executed when the promise is rejected.
With the above example, we generate a random number and resolve/reject the promise depends if the number is grater or smaller than 8 (to get an error every time, we can change the number to 0).
Then, with the next example, we log to the console the result if the promise was resolved or rejected.
A promise can only succeed(resolved) or fail(reject) once. It cannot succeed or fail twice, neither can it switch from success to failure or vice versa.
If a promise has succeeded or failed and you later add a success/failure callback (i.e a .then
), the correct callback will be called, even though the event took place earlier.
If we’re interested only in successful completions, then we can provide only one function argument to
.then
:
catch
If we’re interested only in errors, then we can use null
as the first argument: .then(null, errorHandlingFunction)
. Or we can use .catch(errorHandlingFunction)
, which is exactly the same:
finally
Finally also accept a function handler. finally
is a good handler for performing cleanup or to perform any action regardless if the promise has been resolved or rejected.
The call .finally(f)
is similar to .then(f, f)
in the sense that f
always runs when the promise is settled: be it resolve or reject but with some differences.
- A
finally
handler has no arguments. Infinally
we don’t know whether the promise is successful or not. That’s all right, as our task is usually to perform “general” finalizing procedures. - A
finally
handler passes through results and errors to the next handler.
In the above example, the promise will get resolved and eventually we will see on the console “all good!” (after 1 second). But before that, we use finally
and this will be called before the resolved handler method.
It will act the same if the promise was rejected.
Chaining
Did you see how in the last example I chained .then
to .finally
. This is another advantage for thePromise
object and this is when promises really start to stand out from simple callback patterns.
The idea is that the result is passed through the chain of .then
handlers.
When a handler returns a value, it becomes the result of that promise, so the next .then
is called with it.
The whole chaining works, because a call to
promise.then
returns a promise, so that we can call the next.then
on it.
Keep in mind that technically we can also add many .then
to a single promise. But this is not chaining.
What we did here is just several handlers to one promise. They don’t pass the result to each other; instead they process it independently.
The same as we chaining bunch of .then()
we can use .catch()
to catch error during the chain.
Let’s take a look at a little bit more complex example uses chaining with .then()
and .catch()
we have created 3 different functions where each of them returns a Promise
.
Now, we can call them like that
If, in any point of the chain, the promise would be rejected, we catch the error and print it and as we already learned, finally
will be printed no matter what the promise status would be.