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:
| State | Description |
|---|---|
pending | The operation is still in progress (initial state). |
fulfilled | The operation completed successfully, and the promise has a result. |
rejected | The 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
delaythat returns a Promise. setTimeoutsimulates 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
| Feature | Description |
|---|---|
| Promises | Handle asynchronous operations in a more manageable and readable way |
| States | pending, fulfilled, rejected |
| Methods | .then(), .catch(), .finally() |
| Use Case | Great for HTTP requests, chaining multiple async operations, etc. |
| Benefit | Cleaner than callbacks, better error handling |
4. Async / Await
β What is Async/Await?
asyncmakes a function return a Promise.awaitpauses 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
| Technique | Use Case Example |
|---|---|
| Callbacks | Simple asynchronous tasks, animations |
| Promises | Chained async operations, better error flow |
| Async/Await | Cleaner syntax for async tasks |
π Comparison Table
| Feature | Callback | Promise | Async/Await |
|---|---|---|---|
| Readability | Low (nested, messy) | Medium (chaining) | High (like sync code) |
| Error Handling | Manual | .catch() | try...catch |
| Chaining | Difficult | Easy | Very Easy |
| Syntax | Classic | Modern 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
- Create a callback function to simulate a pizza order that gets delivered in 3 seconds.
- Create a Promise that resolves after 2 seconds and logs a message.
- Convert a Promise-based function into an async/await version.
- 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!
