DEV Community

Cover image for Promises, Promises
benlongcp
benlongcp

Posted on

Promises, Promises

I promise to get to Promises, but first...

Let's say we are running some potentially very time intensive tasks, and because we don't want to just pause our program the moment the interpreter starts to do said task, we need to find a way to have a function that performs an operation and still allows the program to run. This is essentially what callback functions do.

When a function is passed into another function, its resolved value can essentially be stored within that function and then accessed when the outer function is called.

For example, if we wanted to describe a round of duck-duck-goose, we could do it using callbacks:

//we define two functions that take callback function parameters
function duck(cbFunc){
  let duck = "...duck..."
  //and invoke those callbacks on some value
  cbFunc(duck)
}

function goose(cbFunc){
  let goose = "...goose!"
  cbFunc(goose)
}

//now we write a function to play duck-duck-goose
function playDDG(){
  //we call duck passing in a function that...
  duck(person1 => {
    //...logs the input of the passed-in function...
    console.log(person1)
    //...and calls duck passing in a function that...
    duck(person2 => {
      //...logs the input of the passed-in function...
      console.log(person2)
      //...and calls goose passing in a function that...
      goose(person3 =>{
        //...logs the input of the passed-in function.
        console.log(person3)

      })
    })
  })
}

console.log(playDDG())
Enter fullscreen mode Exit fullscreen mode

While this is an effective work-around to the issue of storing a resolved value until it is needed, the syntax of the nested functions can quickly blossom out of the bounds of readability.

This is where I fulfill my earlier promise.

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value (MDN).

While difficult to state it more eloquently than the official documentation, we can maybe say some things in that are true about them to construct a more comprehensive understanding.

Promises are objects, proxies for another value that is not yet accessible by the program

Promise objects are created and given asynchronous code to execute.

New Promise objects take in up to two parameters:
A callback function for a fulfilled promise.
A callback function fora Rejected promise.

Promises have one of three states:

  1. Pending, not resolved or rejected
  2. Fulfilled, the promise has been resolved
  3. Rejected, the promise has been rejected :-(

Promises are used as an alternative to callbacks because they can be chained.

Because it is an object, it has some methods. One of which is. then().

Let's say we have a Promise object:

//it takes a resolve callback and a reject callback
let mathPromise = new Promise((resolve, reject) =>{
  //we do some operation inside
  let three = 3;
  let four = 4;
  if (three + four === 7){
  //if we have met the criteria, we resolve
  resolve(`Yes it is ${three + four}`)
  } else {
  //if not we reject
  reject("...no")

  }})
Enter fullscreen mode Exit fullscreen mode

The .then() method tells us what to do next should the promise be returned resolved. It's basement-dwelling fish-mutant sibling is the .catch() method, to catch that something has gone wrong somewhere and throw an error.

  //if mathPromise returns resolved, then
  mathPromise.then((thenFuncVal) => {
    //log the value of the successful resolve
    console.log(thenFuncVal)
  }).catch((catchFuncVal)=>{
    console.log(catchFuncVal)
  })
Enter fullscreen mode Exit fullscreen mode

Callbacks are stored in the object .then() is called on and a new promise object is returned, thus these method invocations are chainable.

  //we make a new promise
  let wordPromise = new Promise((resolve, reject)=>{
    let word1 = "hello"
    let word2 = "HELLO"
    if (word1 === word2.toLowerCase()){
      resolve("I heard you the first time")
    } else {
      reject("WHAT?")
    }
  })

  //we verify our mathPromise
  mathPromise.then((thenFuncVal) => {
    console.log(thenFuncVal)
    //and if it resolves, we return our wordPromise object
    return wordPromise
  })
  //and then we verify that returned wordPromise
  .then((thenFuncVal) => {
    console.log(thenFuncVal)
  })
  //and if anything gets rejected, we make sure to indicate that rejection
  .catch((catchFuncVal)=>{
    console.log(catchFuncVal)
  })
Enter fullscreen mode Exit fullscreen mode

If we changed a value say in mathPromise such that it was rejected, we would log the value in the reject portion of that conditional, but also we would no longer evaluate wordPromise.

While this aims only to describe the mechanical operation of promise objects, their use in asynchronous programming is indispensable. They preserve the functionality of using callbacks while being able to use object method syntax.

Great resource on promises

MDN: Asynchronous Javascript

MDN: Promises

Top comments (0)