📘 Class Notes: Asynchronous
Programming in JavaScript
1. Introduction to Asynchronous
Programming
1.1 What is Asynchronous Programming?
Definition: Asynchronous programming is a way to execute tasks
without blocking the main thread.
In JavaScript, which is single-threaded, asynchronous programming
allows us to handle tasks like fetching data from a server, reading files,
or handling user input without freezing the browser or application.
👉 Example:
console.log("Start");
setTimeout(() => console.log("Hello after 2s"), 2000);
console.log("End");
Output order:
Start
End
Hello after 2s
2. Why Asynchronous Programming is
Important
JavaScript is Single-Threaded
o Uses an event loop to manage tasks.
o Without async, long-running tasks block execution (e.g., a large
file read).
Real-world use cases:
o Fetching API data
o Animations & user interactions
o Reading/writing to a database
o Network requests
3. The Event Loop
3.1 Components
1. Call Stack: Executes synchronous code line by line.
2. Web APIs (Browser or Node APIs): Handle timers, HTTP requests,
DOM events.
3. Callback Queue (Task Queue): Holds asynchronous callbacks.
4. Event Loop: Moves tasks from queue to call stack when it is free.
👉 Example with setTimeout
console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
Output: 1, 3, 2
4. Asynchronous Patterns in JavaScript
4.1 Callbacks
A function passed as an argument to be executed later.
Oldest form of handling async tasks.
Example:
function fetchData(callback) {
setTimeout(() => {
callback("Data received!");
}, 1000);
}
fetchData((data) => console.log(data));
⚠️Problem: Callback Hell
doStep1((result1) => {
doStep2(result1, (result2) => {
doStep3(result2, (result3) => {
console.log(result3);
});
});
});
Difficult to maintain and debug.
4.2 Promises
Introduced in ES6 (2015) to solve callback hell.
Represents a value that will be available now, later, or never.
States of a Promise:
1. Pending – initial state
2. Fulfilled – operation successful
3. Rejected – operation failed
Creating a Promise
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("Operation successful!");
} else {
reject("Error occurred!");
}
});
myPromise
.then((res) => console.log(res))
.catch((err) => console.error(err));
Chaining Promises
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
4.3 Async/Await (ES2017)
Syntactic sugar over Promises.
Makes asynchronous code look synchronous.
Example:
async function getData() {
try {
const response = await
fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error:", error);
}
}
getData();
⚡ Benefits:
Cleaner, more readable code
Easier error handling with try...catch
5. Advanced Asynchronous Concepts
5.1 Parallel vs Sequential Execution
// Sequential
async function sequential() {
const res1 = await fetch("/data1");
const res2 = await fetch("/data2");
console.log(await res1.json(), await res2.json());
}
// Parallel
async function parallel() {
const [res1, res2] = await Promise.all([
fetch("/data1"),
fetch("/data2")
]);
console.log(await res1.json(), await res2.json());
}
5.2 Promise Methods
Promise.all([p1, p2]) → waits for all to resolve (fails fast).
Promise.race([p1, p2]) → resolves/rejects with the first settled promise.
Promise.allSettled([p1, p2]) → waits for all, regardless of
success/failure.
Promise.any([p1, p2]) → returns first fulfilled promise.
6. Error Handling in Async Code
6.1 With Promises
fetch("invalid-url")
.then(res => res.json())
.catch(err => console.error("Caught error:", err));
6.2 With Async/Await
async function fetchData() {
try {
const res = await fetch("invalid-url");
const data = await res.json();
} catch (error) {
console.error("Error caught:", error);
}
}
7. Real-World Applications
1. Web Applications
a. Load data without refreshing the page (AJAX).
b. Social media feeds (Twitter, Facebook updates).
2. APIs
a. REST API calls (GET, POST, PUT, DELETE).
b. Payment gateways.
3. User Interfaces
a. Autocomplete search suggestions.
b. Loading spinners while waiting for data.
4. Server-side (Node.js)
a. Handling multiple requests concurrently.
b. File system operations.
8. Summary
Synchronous code runs line by line → may block.
Asynchronous code uses callbacks, promises, and async/await.
Event loop is the engine behind async programming.
Promises improve readability; async/await makes it cleaner.
Used everywhere: APIs, databases, UIs, servers.
✅ Key Takeaway: Mastering asynchronous programming is essential for
building responsive, efficient, and modern JavaScript applications.