CallBack, Promises and Async/Await in JS

In this article, wanted to give an overview of CallBack, Promises and Async/Await in JS

Synchronous vs Asynchronous

Synchronous is where in you go through a series of steps and you wait for each step to complete before moving to the next.

There are time consuming operations and you do not want to be blocking the remaining workflow. For instance -> retrieving file, image, performing background operations, etc. In this case we follow the Asynchronous workflow wherein you request for resources and continue the remaining steps.

In order to wait for the async task to complete, we can use CallBack, Promises and Async/Await.

CallBack

Functions are objects in JS and can be passed to another function as an argument. CallBack is when you pass a function as argument and call one function inside another function

For instance, we have the in build functions setTimeout and setInterval which accepts a callback function.

setTimeout(myFunction, 3000);

function myFunction() {
  document.getElementById("demo").innerHTML = "Displayed after 3 seconds";
}

In the above example, the function myFunction is called after 3s.

Another example,

setInterval(()=>{
  let d = new Date();
  document.getElementById("demo1").innerHTML=
  d.getHours() + ":" +
  d.getMinutes() + ":" +
  d.getSeconds();
}, 1000);

The above function that displays the current time is refreshed every second.

A user defined function example is as follows:

Even
<span id="even"></span>

Odd
<span id="odd"></span>

<script>

function compute(numbers,func){
    const myArray = [];
      for (const x of numbers) {
        if (func(x)) {
              myArray.push(x);
        }
      }
      return myArray;
}

document.getElementById("even").innerHTML = compute([1,2,3,4,5,6,7,8],(x)=> x%2 == 0)
document.getElementById("odd").innerHTML = compute([1,2,3,4,5,6,7,8],(x)=> x%2 != 0)

Promises

Asynchronous programming is difficult to write and debug and hence we have promises.

A promise basically means we would have something in the future for sure. A Promise has 3 states and the result depend on the particular promise state.

  1. Pending -> result is undefined
  2. Fulfilled -> result is a value
  3. Rejected -> result is an error object

Screen Shot 2022-11-09 at 1.25.09 PM.png

An example of using Promise

//Producing code
let myPromise = new Promise(function(resolve, reject) {
  const condition = true;

  if (condition) {
    resolve("OK");
  } else {
    reject("Error");
  }
});

//Consuming code
myPromise
    .then((value) => {document.getElementById("demo").innerHTML = value})
    .catch((error) => {document.getElementById("demo").innerHTML = error})

Async/Await

Using the keyword async before a function means that the function would return a promise.

So, instead of using promises as in the previous example, we could use the following

//Producing code
async function myFunction(){
    return "OK";
};

//Consuming code
myFunction()
    .then((value) => {document.getElementById("demo").innerHTML = value})

The await keyword can only be used inside an async function Using the await keyword makes the function pause the execution and wait for the resolved promise.

An example is as follows

async function myDisplay() {
  let myPromise = new Promise(function(resolve) {
    setTimeout(function() {resolve("Display text after 10s");}, 10000);
  });
  document.getElementById("demo").innerHTML =  await myPromise;
  document.getElementById("demo").innerHTML = "Displayed after timeout when await keyword is used"
}

myDisplay();

Here if await is used, then the execution waits for 10s before displaying the final text. Otherwise, the final text is displayed immediately.

Conclusion

In this article, we had a quick overview of using CallBack, Promises and Async/Await in JS. The most commonly used is the async/await keywords which can be used effectively for performing async operations and waiting for a result.