JavascriptTutorials

JavaScript Promises

A Promise, is an object with an expectation that a value will be produced usually from an asynchronous task.

What is a promise?

Promises in JavaScript are used to retrieve a value from a task that is performed asynchronously, for example making an API call to an endpoint, and expecting that a value will be returned. The key word is ‘expecting‘, since we are waiting for a response, so that we can use the data returned to perform some other tasks. Lets take a quick look at the structure of a promise.

new Promise(function(resolve, reject){
  
    resolve('Success')
    
    // reject('Failed')
  
})

According to JavaScript.info a promise is made up of a few main components: A “producing code” and a “consuming code”. Then there is the promise itself that acts as a link between the two.

new Promise(function(resolve, reject) {
  
  setTimeout(function(){resolve('success');},3000); // Producing code
  
});

I have commented on the above code snippet what the producing code is, we will discuss the consuming code later.

The producing code is where our asynchronous actions take place, e.g calls to an API, large calculations etc. There is another part of the code I should also highlight:

function(resolve, reject) {
  // executor
} 

This part is simply known as the executor, and will run whatever is inside the curly braces. It is ran automatically, and contains two arguments, resolve and reject. Resolve and reject are used to determine the outcome of the producing code. For example if the producing code succeeds in making a call to an API and data is returned, we can use resolve to return the data. If it fails, then we can use reject to return an error, and let the developer or user know the call has failed.

Promise States

I would like to dive a little deeper into resolve and reject and talk about the state within a Promise. I mentioned that we use resolve or reject to determine the outcome of the executor code, to describe what the promise is doing, we actually use the terms fulfilled and rejected, these are states. There is also an additional state called pending where a promise has yet to be fulfilled or rejected.

So just to clarify a Promise can be in 3 different states: Pending, Fulfilled or Rejected. A good way to check out the different states is by using the Google Chrome console or the console of the browser you are using although I recommend Chrome.

Below I have included a screenshot in Chrome of both pending and fulfilled to help demonstrate. Since rejected returns an error, I’m unable to show the state for rejected.

Pending

Fulfilled

  • Status
  • Value
  • Consumers

As you can see from the above screenshots, there is a status(state) of the Promise as well as a value. When the promise is pending, the value is undefined, because we have yet to be fulfilled. When we use the resolve callback and provide a value, that value gets returned.

Consumers

The consuming code or consumers are a set of functions registered to the Promise that can use returned values from the producing code. There are three different types of consumers.

.then()

let promise = new Promise(function(resolve, reject){
  
    resolve('Success')
    
    // reject('Failed')
  
}).then(
  (result) => console.log(result),
  (error) => console.log(error)
  
)

The then consumer will run after the promise has been fulfilled or rejected. It takes two arguments both of them are callback functions. The first function will run if the promise was successful and fulfilled. The second function will run if there was an error. Most developers will use only the first function and use a catch to pick up any errors.

.catch()

let promise = new Promise(function(resolve, reject){
  
    reject('Failed')
  
}).catch(
  (error) => console.log(error)
  
)

The catch consumer is fairly straight-forward. If the promise is rejected, then the .catch() will return the rejected value. In this case it is ‘Failed’.

.finally()

let promise = new Promise(function(resolve, reject){
  
  reject('Failed')
  
}).finally(
  () => {
    // insert code regardless of rejected or fulfilled
  }
  
)

The finally consumer runs whether or not the promise was rejected or fulfilled, it is mainly use to clean up code and has no arguments.

References
https://javascript.info/promise-basics
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://jsbin.com/ – for help with creating viewable code