Callbacks JavaScript

Madhu sudhanMadhu sudhan
6 min read

What are callbacks ?

Before going any further we need to understand what is a callback ?

Any function which passed as parameter to another function can be categorized as callback function. which can be invoked during the program execution and perform operations which the callback function holds.

function sayHello(name, callback) {
  console.log("Hello, " + name );
  callback();
}
function sayGoodbye() {
  console.log("Goodbye!");  
}
sayHello("John", sayGoodbye);

from the above example we are passing the sayGoodBye() function as the parameter to another function sayHello().

Why do we need callbacks

As we all know JavaScript is synchronous and single threaded language. to make the JavaScript work asynchronously we use callbacks.
say we have an event driven application and and our program is waiting for that particular event to occur which never happens, this causes our execution to block and wait infinitely which no one wants or say we have a very big file to read which takes some time if not more. this reading operation halts the program execution until it completes the read operation or it may even fail if the file doesn’t exist at all, we should not let our entire program to come down crumbling. To encounter such problems callbacks can be used.
Using the callbacks provide us with flexibility, asynchronous behavior and better error handling.

fs.readFile('example.txt', (err, data) => {
  if (err) throw err;
  console.log(data.toString());
});

Uses of callbacks.

  • Asynchronous operations

  • promises and async/await

  • Event driven programming

  • Error handling

Why we need a better solution than callbacks

while dealing with the callbacks one might encounter a special thing called callback hell or widely popular with the name Pyramid of doom.
So what is a callback hell ?
say we have a 100 callbacks each of which is nested with in the other that leads the program to work with each of the callback synchronously making the execution time grow faster and another side effect of this callback hell is readability , It makes harder to read a 100 nested callbacks., obviously.
when the program grows horizontally rather than traditional way of growing vertically is referred as pyramid of doom.
to counter the difficulties of readability and avoid the callback hell we do need a better solution.

fs.readFile('file1.txt', (err, data1) => {
  if (err) throw err;
  fs.readFile('file2.txt', (err, data2) => {
    if (err) throw err;
   fs.writeFile('output.txt', data1 + data2, (err) => {
      if (err) throw err;
      console.log('Files processed successfully');
    });
  });
});

What is promise ?

A promise is a special object which indicates eventual resolve or rejection of a asynchronous operation.
Promise is constructor and takes a callback function of two parameters, so to create a promise we have to use key word new to create a new promise object.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('callback blog');
  },0);
});

the promises allows you to handle asynchronous tasks such as fetching data from an API or chaining another promise once the operation is complete. A promise can be in one of three states: pending, resolved or rejected . You use .then() function to handle success and .catch() to handle the eventual rejection of the promise.

Error handling with promises

Promises provide us with the cleaner and more readable way to deal with asynchronous operations. They avoid nesting by allowing you to chain other promises. errors while using the promises can be handled using the catch()

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("data fetched");
        }, 2000);
    });
}
fetchData()
    .then((data) => {
        console.log(data); 
    }).catch((error) => {
        console.log("Error:", error);
    });

Promise chaining

Promise chaining is the method of executing multiple asynchronous tasks in sequence by chaining them using .then(). Each .then() block processes the result of the previous promise and can return a new value or next promise this goes on to the end.

function Task1() {
    return new Promise((resolve) => {
        setTimeout(() => resolve("Task 1 complete"), 1000)
    });
}
function Task2(result) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(result + " -> Task 2 complete"), 1000)
    })
}
Task1()
    .then((result) => {
        console.log(result)
        return Task2(result)
    })
    .then((result) => {
        console.log(result)
    })

what are the Promise APIs

  1. Promise.all()
    Promise.all() is a method that takes an array of promises and returns a single promise. This promise resolves only when all the promises in the array resolve or it rejects as soon as any of the promises in the array rejects.
const promise1 = new Promise((resolve) => setTimeout(() => resolve('first promise'), 1000))
const promise2 = new Promise((resolve) => setTimeout(() => resolve('second promise'), 2000))
Promise.all([promise1, promise2])
    .then((results) => {
        console.log(results)
    })
    .catch((error) => {
        console.log(error);
    });
  1. Promise.allSettled()

Promise.allSettled() is a method that takes an array of promises and returns a promise that resolves only when all of the input promises settle (either resolved or rejected). it never rejects and instead returns an array of objects, each representing the result of each promise, .catch() is optional as it never rejects.

const promise1 = new Promise((resolve) => setTimeout(() => resolve("resolved "), 1000));
const promise2 = new Promise((resolve,reject) => setTimeout(() => reject("rejected"), 2000));

Promise.allSettled([promise1, promise2])
  .then((results) => {
    results.forEach((result) => console.log(result));
  });
  1. Promise.race()

Promise.race() is a method that takes an array of promises and returns a single promise. as soon as one of the promises in the array settles (either resolves or rejects), whichever happens first.

const promise1 = new Promise((resolve) => setTimeout(() => resolve("First resolved!"), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Second resolved!"), 2000));

Promise.race([promise1, promise2])
  .then((result) => console.log(result))
  .catch((error) => console.log(error));
  1. Promise.any()

Promise.any() is a method that takes an array of promises and returns a single promise that resolves as soon as any one of the promises is fulfilled. If none of the promises are fulfilled and all of them reject, it returns an Aggregate Error.

const promise1 = new Promise((resolve, reject) => setTimeout(() =>reject("Promise 1 rejected"), 1000))
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Promise 2 resolved"), 2000))
Promise.any([promise1, promise2])
.then((result) => console.log(result))
  .catch((error) => console.log(error))

Async / Await

Async/Await in JavaScript are built on top of promises to provide us with better readability and better manageable code.
async/await lets us write asynchronous code which looks and acts like synchronous.

async function asynchronousFunction() {
return "hello" 
}
asynchronousFunction().then(data=> console.log(data))

Any function which is declared as async will return a promise which need to handled even though we didn’t return a promise object.

async function fetchData() {
    const response = await fetch('URL')
    const data = await response.json()
    return data
}
fetchData().then(data => console.log(data))

whenever we use await to handle a promise it halts the execution of our program until the promise resolve or rejects, if the promise resolves it returns the resolved value or if the promise rejects it throws an error which need to handled using try and catch block, all the promise handling statements are written inside try block and the errors are handled using catch block.

0
Subscribe to my newsletter

Read articles from Madhu sudhan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Madhu sudhan
Madhu sudhan