Logo
HTMLCSSJavaScriptReactjsnewContactUpdates

Get started today

HTMLCSSJavaScriptReactjsnewContactUpdates

Tools

Resume BuilderQR GeneratorVS Code Editor

Connect

GitHubWhatsApp Channel
exception handling
non promise based apis

Asynchronous JavaScript

By Saket Bhatnagar•June 15, 2025•Beginner to Intermediate

Table of Contents

  1. Introduction to Asynchronous JavaScript
  2. Ways to Handle Asynchronous Operations
  3. Common Asynchronous Operations
  4. Best Practices

Introduction to Asynchronous JavaScript

  1. 1Asynchronous programming allows non-blocking operations in JavaScript
  2. 2In synchronous programming, tasks are executed one after another, blocking the execution until each task completes
  3. 3Why do we need Asynchronous JavaScript?
    • To handle time-consuming operations without blocking the main thread
    • To improve application performance and user experience
    • To handle operations like:
      • Fetching data from servers (API calls)
      • Reading files (Node.js)
      • Complex calculations
      • Database operations (Node.js)

Ways to Handle Asynchronous Operations

  1. 1

    Callbacks

    Callbacks are functions passed as arguments to another function that will be executed later.

    1// Example of callback
    2function fetchData(callback) {
    3 setTimeout(() => {
    4 const data = { id: 1, name: 'John' };
    5 callback(data);
    6 }, 2000);
    7}
    8
    9fetchData((result) => {
    10 console.log(result); // Runs after 2 seconds
    11});
  2. 2

    Promises

    Promises are objects representing the eventual completion (or failure) of an asynchronous operation.

    1// Example of Promise
    2const fetchUserData = new Promise((resolve, reject) => {
    3 setTimeout(() => {
    4 const user = { id: 1, name: 'John' };
    5 resolve(user);
    6 // reject('Error fetching user');
    7 }, 2000);
    8});
    9
    10fetchUserData
    11 .then(user => console.log(user))
    12 .catch(error => console.error(error));
  3. 3

    Async/Await

    Async/await makes complicated code simpler to write and understand. It helps developers write code that needs to wait for things (like getting data from the internet) in a way (that's easier to read).

    1// Example of async/await
    2async function fetchUser() {
    3 try {
    4 const response = await fetch('https://api.example.com/user');
    5 const user = await response.json();
    6 console.log(user);
    7 } catch (error) {
    8 console.error('Error:', error);
    9 }
    10}
  4. 4

    Callback Hell

    Callback Hell (also known as Pyramid of Doom) occurs when we have multiple nested callbacks, making the code difficult to read and maintain.

    1// Example of Callback Hell
    2fetchUserData((user) => {
    3 console.log('Fetched user');
    4 getUserPosts(user.id, (posts) => {
    5 console.log('Fetched posts');
    6 getPostComments(posts[0].id, (comments) => {
    7 console.log('Fetched comments');
    8 getCommentAuthor(comments[0].id, (author) => {
    9 console.log('Fetched author');
    10 // Code becomes deeply nested and hard to read
    11 }, (error) => {
    12 console.error('Error fetching author:', error);
    13 });
    14 }, (error) => {
    15 console.error('Error fetching comments:', error);
    16 });
    17 }, (error) => {
    18 console.error('Error fetching posts:', error);
    19 });
    20}, (error) => {
    21 console.error('Error fetching user:', error);
    22});
  5. 5

    Solving Callback Hell

    We can solve callback hell using Promises or async/await:

    1// Using Promises
    2fetchUserData()
    3 .then(user => {
    4 console.log('Fetched user');
    5 return getUserPosts(user.id);
    6 })
    7 .then(posts => {
    8 console.log('Fetched posts');
    9 return getPostComments(posts[0].id);
    10 })
    11 .then(comments => {
    12 console.log('Fetched comments');
    13 return getCommentAuthor(comments[0].id);
    14 })
    15 .then(author => {
    16 console.log('Fetched author');
    17 })
    18 .catch(error => {
    19 console.error('Error:', error);
    20 });
    21
    22// Using async/await (even cleaner)
    23async function fetchUserDataChain() {
    24 try {
    25 const user = await fetchUserData();
    26 console.log('Fetched user');
    27
    28 const posts = await getUserPosts(user.id);
    29 console.log('Fetched posts');
    30
    31 const comments = await getPostComments(posts[0].id);
    32 console.log('Fetched comments');
    33
    34 const author = await getCommentAuthor(comments[0].id);
    35 console.log('Fetched author');
    36 } catch (error) {
    37 console.error('Error:', error);
    38 }
    39}
  6. 6
    Problems with Callback Hell:
    • Code becomes difficult to read and maintain
    • Error handling becomes complicated
    • Debugging becomes challenging
    • Code becomes less reusable

Common Asynchronous Operations

  1. 1setTimeout and setInterval
    1// setTimeout - runs once after delay
    2setTimeout(() => {
    3 console.log('Runs after 2 seconds');
    4}, 2000);
    5
    6// setInterval - runs repeatedly
    7const timer = setInterval(() => {
    8 console.log('Runs every 1 second');
    9}, 1000);
    10
    11// Clear interval
    12clearInterval(timer);
  2. 2API Calls using fetch
    1// Using fetch with async/await
    2async function getUsers() {
    3 try {
    4 const response = await fetch('https://api.example.com/users');
    5 const users = await response.json();
    6 return users;
    7 } catch (error) {
    8 console.error('Error fetching users:', error);
    9 }
    10}

Best Practices

  1. 1Always handle errors in asynchronous operations using try-catch or .catch()
  2. 2Avoid callback hell by using Promises or async/await
  3. 3Use Promise.all() when dealing with multiple independent promises
  4. 4
    Note: Modern JavaScript primarily uses Promises and async/await for handling asynchronous operations as they provide better readability and error handling compared to callbacks.

Share this article

Last updated: July 15, 2025

Join Our Community

Login to Join

© 2025 Saket Bhatnagar. All rights reserved.

    ☕