What the Heck is Async/Await, Callbacks, and Promises? A Simplified Guide to Asynchronous JavaScript

What the Heck is Async/Await, Callbacks, and Promises? A Simplified Guide to Asynchronous JavaScript


Consider three tasks below

  1. Teach (Takes 1 hr)

  2. Buy iPad (Takes 1hr)

  3. Cook Dinner (Takes 1 hr)

In a Synchronous way, I alone will do 3 tasks sequentially. One by One. Thus, took 3 Hours.

In an Asynchronous way, I teach and meanwhile told my brother to buy an IPad and sister to cook dinner. Thus, it took 1 hour.

// Code for stopwatch

var counter = 1;

function printCounter(){
  console.clear();
  console.log(counter);
  counter = counter+1;
}

setInterval(printCounter, 1000);

JS Runtime/Event Loop


Event Loop is a way of running asynchronous code (background task) in JavaScript.

An async code is offloaded to “WebAPIs”, (which is on separate thread) or so it keeps running in the background and doesn't block the main thread. When this background task is completed, its callback is added to a “Callback Queue” and is pushed to “Call Stack”(when it is empty) by “Event Loop” and hence that callback executes on the main thread.

In the code below setTimeout, an async code, is offloaded to WebAPIs and its callback is pushed into in the callback queue when time ends. Its callback is executed only when Call Stack is empty or there is no long-running task.

var counter = 1;

function printCounter(){
  console.clear();
  console.log(counter);
  counter = counter+1;
}

setTimeout(printCounter, 3000);

var counter = 0;
for(var i = 0; i < 3; i++){
    counter = counter + i;
}

<aside> ⭐ WebAPI runs on a separate thread for async/background task, while the JS thread is for the main task.

</aside>

Additional Resources

What is the JavaScript event loop really all about - Java Brains

What the heck is the event loop anyway? | Philip Roberts | JSConf EU

Callback & Promises


Callback : When we want to call a function after a task finishes. Like I want my friend to get Medicine2 once I receives the Medicine1 from him. Below is the code for the same.

function getMedicine1(){
    console.log("1 Received");
    setTimeout(getMedicine2, 2000);
}

function getMedicine2(){
    console.log("2 Received");
}

setTimeout(getMedicine1, 1000);

Callback Hell : When the code above is written like below, this usually happens in complex code, which too much nested. This super ugly code is referred as “Callback Hell”.

setTimeout(function getMedicine1(){
 console.log("1 Received");
  setTimeout(function getMedicine2(){
    console.log("2 Received"); 
  }, 2000);
}, 1000);

Promises : In solution to callback hell, promises were introduced.

function getMedicine1() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log("1 Received")
      resolve();
    }, 1000);
  });
}

function getMedicine2() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
            console.log("2 Received")
      resolve();
    }, 2000);
  });
}

getMedicine1()
    .then(getMedicine2())

Another Promise example: Simulating an Asynchronous Operation (e.g., making an API request)

const fetchData = new Promise((resolve, reject) => {
  // Simulating an asynchronous operation (e.g., making an API request)
  setTimeout(() => {
    const data = { name: "John Doe", age: 25 };
    // Simulating a successful response
    resolve(data);
    // Simulating an error
    // reject("Failed to fetch data");
  }, 2000);
});

fetchData
  .then((result) => {
    console.log("Data fetched:", result);
    // Perform additional operations or return another promise
    // return someOtherAsyncOperation();
  })
  .catch((error) => {
    console.error("Error:", error);
  });

Summarisation of Callback and Promise

Callbacks: Function provided to be called back when the task completes. Promises: Immediate promise received, allowing chaining of functions based on fulfillment or rejection.

function printContent(error, data) {
    console.log(data);
}

fs.read("file.txt", printContent) // Callback Version
fs.read("file.txt").then(printContent) // Promise Version