Absolutely! Here’s your well-documented, beginner-friendly class on one of the most powerful topics in modern JavaScript:


Class 14: Asynchronous JavaScript – Callbacks, Promises, Async/Await

Welcome to Class 14, where we dive deep into Asynchronous JavaScriptβ€”an essential part of building smooth, non-blocking web applications. Today, we’ll explore:

  • What asynchronous JavaScript means
  • Callbacks
  • Promises
  • Async/Await
  • Practical examples
  • Use cases
  • Comparison
  • Common mistakes

πŸ”„ 1. What is Asynchronous JavaScript?

JavaScript is single-threaded, meaning it runs one task at a time. But in real life, you often deal with tasks that take time, such as:

  • Fetching data from an API
  • Reading from a file
  • Waiting for a user interaction

To avoid blocking the main thread, JavaScript uses asynchronous programming to handle such operations in the background and respond when they’re done.


2. Callbacks

βœ… What is a Callback?

A callback is a function passed as an argument to another function, to be executed later.

🧠 Syntax:

function doSomething(callback) {
  // some work
  callback();
}

πŸ”§ Example 1 – Basic Callback

function greet(name, callback) {
  console.log("Hi, " + name);
  callback();
}

function sayBye() {
  console.log("Goodbye!");
}

greet("Shohel", sayBye);

πŸ”§ Example 2 – Simulating Async Operation

function fetchData(callback) {
  setTimeout(() => {
    console.log("Data fetched");
    callback();
  }, 2000);
}

fetchData(() => {
  console.log("Callback executed after fetch");
});

❌ Callback Hell (Problem)

setTimeout(() => {
  console.log("Step 1");
  setTimeout(() => {
    console.log("Step 2");
    setTimeout(() => {
      console.log("Step 3");
    }, 1000);
  }, 1000);
}, 1000);

Of course, Shohel! Here’s an enhanced and detailed rewrite of the “3. Promises” section of your JavaScript Class 14. I’ve expanded the explanation, provided deeper insights, added use cases, and included more diverse examples for beginner to intermediate learners.


3. Promises (In-Depth)

βœ… What is a Promise?

A Promise in JavaScript is an object that represents the eventual completion or failure of an asynchronous operation and its resulting value. Promises are introduced in ES6 (ECMAScript 2015) to solve problems like callback hell and make asynchronous code easier to read and maintain.

You can think of a Promise as a container for a value that will be available sometime in the future, whether the operation succeeds or fails.


πŸ“¦ States of a Promise

A Promise has three states:

StateDescription
pendingThe operation is still in progress (initial state).
fulfilledThe operation completed successfully, and the promise has a result.
rejectedThe operation failed, and the promise has an error reason.

🧠 Basic Syntax of a Promise

const promise = new Promise((resolve, reject) => {
  // async task here
  if (/* task successful */) {
    resolve(result); // fulfilled
  } else {
    reject(error); // rejected
  }
});
  • resolve(value) – marks the promise as fulfilled, returning a value.
  • reject(error) – Marks the promise as rejected, returning an error.

πŸ”§ Example 1 – Creating and Consuming a Simple Promise

let task = new Promise((resolve, reject) => {
  let done = true;

  if (done) {
    resolve("βœ… Task Completed Successfully!");
  } else {
    reject("❌ Task Failed!");
  }
});

// Consuming the promise
task
  .then((message) => {
    console.log("Success:", message);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

πŸ” Explanation:

  • new Promise(...) Creates a promise.
  • Inside the promise, we simulate a task being done or failed.
  • .then() handles the success.
  • .catch() handles the error.

πŸ”§ Example 2 – Promise with setTimeout (Asynchronous Delay)

function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`⏱ Waited for ${ms / 1000} second(s)!`);
    }, ms);
  });
}

// Usage
delay(2000).then((msg) => console.log(msg));

πŸ” Explanation:

  • We create a function delay that returns a Promise.
  • setTimeout simulates an async operation.
  • After the time passes, it calls resolve() with a message.
  • The caller uses .then() to act after the delay.

πŸ”§ Example 3 – Promise with Condition and setTimeout

function simulateDownload(file) {
  return new Promise((resolve, reject) => {
    console.log(`Starting download of ${file}...`);

    setTimeout(() => {
      const success = Math.random() > 0.3; // 70% chance of success

      if (success) {
        resolve(`${file} downloaded successfully βœ…`);
      } else {
        reject(`Failed to download ${file} ❌`);
      }
    }, 3000);
  });
}

// Consuming the promise
simulateDownload("video.mp4")
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

πŸ”§ Example 4 – Chaining Promises

function fetchUser(id) {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ id: id, name: "Shohel" }), 1000);
  });
}

function fetchPostsByUser(user) {
  return new Promise((resolve) => {
    setTimeout(() => resolve([`Post 1 by ${user.name}`, `Post 2 by ${user.name}`]), 1000);
  });
}

// Chaining
fetchUser(1)
  .then((user) => {
    console.log("User:", user);
    return fetchPostsByUser(user);
  })
  .then((posts) => {
    console.log("Posts:", posts);
  })
  .catch((err) => console.error("Error:", err));

❌ Common Mistakes with Promises

1. Not returning inside .then()

function bad() {
  return new Promise((resolve) => resolve("Hi"));
}

bad()
  .then((res) => {
    console.log(res);
    // forgot to return another promise here
  })
  .then((second) => {
    // second is undefined
    console.log(second); 
  });

βœ… Correct:

bad()
  .then((res) => {
    console.log(res);
    return "Next Step";
  })
  .then((second) => {
    console.log(second); // "Next Step"
  });

🧠 Summary

FeatureDescription
PromisesHandle asynchronous operations in a more manageable and readable way
Statespending, fulfilled, rejected
Methods.then(), .catch(), .finally()
Use CaseGreat for HTTP requests, chaining multiple async operations, etc.
BenefitCleaner than callbacks, better error handling

4. Async / Await

βœ… What is Async/Await?

  • async makes a function return a Promise.
  • await pauses the function execution until the Promise is resolved.

πŸ”§ Syntax:

async function myFunction() {
  let result = await somePromise();
}

πŸ”§ Example 1 – Simple Usage

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("Data loaded"), 2000);
  });
}

async function showData() {
  console.log("Loading...");
  let data = await fetchData();
  console.log(data); // "Data loaded"
}

showData();

πŸ”§ Example 2 – Error Handling with try...catch

async function loadData() {
  try {
    let response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Failed to load:", error);
  }
}

loadData();

βœ… Use Cases for Each

TechniqueUse Case Example
CallbacksSimple asynchronous tasks, animations
PromisesChained async operations, better error flow
Async/AwaitCleaner syntax for async tasks

πŸ” Comparison Table

FeatureCallbackPromiseAsync/Await
ReadabilityLow (nested, messy)Medium (chaining)High (like sync code)
Error HandlingManual.catch()try...catch
ChainingDifficultEasyVery Easy
SyntaxClassicModern ES6+Modern ES8+

🧠 Common Mistakes

❌ Using await outside async

let data = await fetch(...); // ❌ SyntaxError

βœ… Fix:

async function fetchData() {
  let data = await fetch(...);
}

❌ Forgetting to return in a promise

new Promise((resolve, reject) => {
  setTimeout(() => "Done", 1000); // ❌ no resolve
});

βœ… Fix:

new Promise((resolve, reject) => {
  setTimeout(() => resolve("Done"), 1000);
});

🧩 Practical Project Example – Fetch API with Async/Await

async function getUserData(userId) {
  try {
    const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
    const user = await response.json();
    console.log(`Name: ${user.name}, Email: ${user.email}`);
  } catch (error) {
    console.error("Error fetching user:", error);
  }
}

getUserData(1);

πŸ“ Homework

  1. Create a callback function to simulate a pizza order that gets delivered in 3 seconds.
  2. Create a Promise that resolves after 2 seconds and logs a message.
  3. Convert a Promise-based function into an async/await version.
  4. Write a program that fetches post titles from a REST API using async/await.

🎯 Key Takeaways

  • Callbacks are the foundation of async JavaScript but can get messy.
  • Promises improve readability and allow chaining and better error handling.
  • Async/Await makes code cleaner and easier to write, especially with try/catch.

Would you like me to prepare Class 15 next? Let me know the topic you’d like to coverβ€”JavaScript modules, error handling, DOM manipulation, or anything else!

Comment

Your email address will not be published. Required fields are marked *