Asynchronous Programming
What is a Callback?
A callback is a function that is passed as an argument to another function.
The main function executes the callback later, when needed.
Callbacks are mostly used for asynchronous operations (like reading files,
making API calls, or timers).
Example 1: A Simple Callback Function
function greet(name, callback) {
console.log("Hello, " + name);
callback(); // Calling the callback function
}
function sayGoodbye() {
console.log("Goodbye!");
}
greet("Sai", sayGoodbye);
What’s Happening Here?
1. We have a function greet(name, callback) .
2. It takes two parameters:
name : The person's name.
callback : Another function to be called later.
3. Inside greet() , we first print "Hello, Sai", then call the callback() , which prints
"Goodbye!".
📌 Output:
Asynchronous Programming 1
Hello, Sai
Goodbye!
Example 2: Callback for Asynchronous Code
Callbacks are useful when dealing with delayed operations, like setTimeout() .
function fetchData(callback) {
console.log("Fetching data...");
setTimeout(() => {
console.log("Data received!");
callback(); // Calling the callback function after data is received
}, 2000);
}
function processData() {
console.log("Processing data...");
}
fetchData(processData);
What’s Happening Here?
1. fetchData() starts fetching data.
2. It waits 2 seconds using setTimeout() .
3. After 2 seconds, "Data received!" is printed.
4. Then, the callback() function ( processData() ) is called, printing "Processing data..." .
📌 Output:
Fetching data...
(Data comes after 2 seconds)
Asynchronous Programming 2
Data received!
Processing data...
Why Do We Use Callbacks?
JavaScript runs code line by line and doesn’t wait for slow tasks.
Callbacks make sure some code runs after an operation is done.
Callback Hell (The Problem with Callbacks)
Callbacks are useful, but too many nested callbacks make code hard to read.
This is called Callback Hell.
setTimeout(() => {
console.log("Task 1 done");
setTimeout(() => {
console.log("Task 2 done");
setTimeout(() => {
console.log("Task 3 done");
}, 1000);
}, 1000);
}, 1000);
📌 Output (after 3 seconds):
Task 1 done
Task 2 done
Task 3 done
😵 The problem? The code is deeply nested and hard to manage.
How to Fix Callback Hell?
We use Promises and Async/Await, which we’ll cover next when you say "next".
Asynchronous Programming 3
Summary
1. A callback is a function passed as an argument to another function and is
executed later.
2. Used for async tasks (fetching data, file reading, timers).
3. Too many nested callbacks lead to Callback Hell, making code hard to read.
1️⃣ What is
.then()
.then() in Promises?
is used to handle the result of a Promise when it resolves (succeeds).
Example: Using .then()
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received!");
}, 2000);
});
promise.then((data) => {
console.log(data); // "Data received!" (after 2 seconds)
});
✅ How It Works?
resolve("Data received!") means the promise is fulfilled.
.then((data) => {...}) runs after the promise is resolved and receives the resolved
value ( "Data received!" ).
2️⃣ What is a Response in Fetch API?
When we use fetch() , it sends a request to a server and returns a Response
object.
Asynchronous Programming 4
Example of Fetching Data
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json()) // Convert response to JSON
.then((data) => console.log(data)) // Log the data
.catch((error) => console.error("Error:", error));
✅ Breaking It Down:
1. fetch("URL") sends a request to the server.
2. .then((response) => response.json())
response.json() converts the response from text to JavaScript Object.
3. .then((data) => console.log(data))
We print the data received from the API.
📌 Example Response from the API
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
3️⃣Request)
Stopping a Request (Abort a Fetch
If a request is taking too long, we can abort it using the AbortController() .
Example:
const controller = new AbortController();
const signal = controller.signal;
Asynchronous Programming 5
fetch("https://jsonplaceholder.typicode.com/todos/1", { signal })
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Fetch aborted or failed:", error));
// Stop the request after 1 second
setTimeout(() => {
controller.abort(); // This cancels the request
console.log("Request Aborted!");
}, 1000);
✅ How It Works?
controller.abort() stops the request if it’s taking too long.
If aborted, .catch() runs and prints "Fetch aborted or failed".
4️⃣ Status Codes & Status Text
When we make a request, the server returns a status code to tell us what
happened.
Common Status Codes
Code Meaning
200 ✅ OK (Success)
201 ✅ Created (New data added)
400 ❌ Bad Request (Wrong request)
401 ❌ Unauthorized (Need login)
404 ❌ Not Found (URL is wrong)
500 ❌ Server Error (Problem on the server)
Example: Checking Response Status
Asynchronous Programming 6
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => {
if (!response.ok) {
throw new Error(`Error: ${response.status} - ${response.statusText}`);
}
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error(error));
✅ How It Works?
response.ok is true if status is 200-299.
response.status returns the status code (e.g., 200, 404).
response.statusText gives a short message (e.g., "OK", "Not Found").
5️⃣ response.json() vs response.text()
After fetching data, we need to convert it.
Difference:
Method Converts Response To Example Use Case
.json() JavaScript Object API responses (JSON format)
.text() Plain Text Fetching simple text files
Example of .json()
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json()) // Convert to JSON object
.then((data) => console.log(data)); // Prints JavaScript object
✅ Output (JSON object)
Asynchronous Programming 7
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Example of .text()
fetch("https://example.com/textfile.txt")
.then((response) => response.text()) // Convert to text
.then((data) => console.log(data)); // Prints plain text
✅ Output (Plain Text)
Hello, this is a text file content!
6️⃣Info)URL Headers (Getting & Sending Extra
Headers are used to send extra info like authentication, content type, etc.
Example: Adding Headers in Fetch
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
headers: {
"Content-Type": "application/json", // Tells server we are sending JSON
"Authorization": "Bearer myToken123" // Example authentication token
},
body: JSON.stringify({ title: "New Post", body: "Hello World!", userId: 1 })
})
.then(response => response.json())
Asynchronous Programming 8
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
✅ How It Works?
headers send extra information (like "Content-Type": "application/json" ).
body contains the data we send in JSON format.
🚀 Final Recap
1️⃣ is used to handle promise results.
.then()
2️⃣ Response Object contains status, headers, and data.
3️⃣ Stopping Requests is done using .
AbortController()
4️⃣ Status Codes tell if a request is successful or failed.
5️⃣ vs - JSON for APIs, Text for simple files.
.json() .text()
6️⃣ Headers help send additional information (e.g., Content-Type ).
1️⃣ Why Do We Need Promises?
In JavaScript, some tasks take time to complete, like:
Fetching data from a server 🌎
📄
Reading a file
Running a timer ⏳
JavaScript does not wait for these tasks to finish. Instead, it keeps running the
next code immediately.
📌 Example of a slow task:
setTimeout(() => {
console.log("Task Complete!");
}, 3000); // Runs after 3 seconds
console.log("Next task");
Asynchronous Programming 9
✅ Output:
Next task
Task Complete! (after 3 seconds)
Problem? The second line runs before the first task is done!
2️⃣ What is a Promise?
A Promise is used when we have a task that takes time and we want to handle its
result later.
A Promise has three states:
Pending 🟡 (Task is running)
Resolved (Fulfilled) ✅ (Task finished successfully)
Rejected (Failed) ❌ (Task failed)
📌 Creating a Promise
let myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Task completed!"); // Successfully finished
}, 2000);
});
✅ How It Works?
The new Promise() runs immediately.
Inside, we call resolve() if the task is successful.
The task runs for 2 seconds, then Promise is resolved.
3️⃣ Using .then() to Handle a Promise
Now, how do we use the promise?
We use .then() to get the result when the task is finished.
Asynchronous Programming 10
📌 Example with .then()
myPromise.then((message) => {
console.log(message);
});
✅ Output after 2 seconds:
Task completed!
📌 Explanation
.then((message) => {...}) runs when the promise is resolved.
message gets the value "Task completed!" .
4️⃣ What is reject() ?
Sometimes, the task fails. In that case, we use reject() instead of resolve() .
📌 Example of Rejection
let myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
let success = false; // Simulating failure
if (success) {
resolve("Success!");
} else {
reject("Error: Task failed!");
}
}, 2000);
});
myPromise
.then((message) => {
console.log(message);
})
Asynchronous Programming 11
.catch((error) => {
console.error(error);
});
✅ Output after 2 seconds:
Error: Task failed!
📌 Explanation
If success is false , reject() runs.
.catch() handles the error message.
5️⃣ Fetching Data with Promises
We use fetch() to get data from a server. It returns a Promise, so we use .then() to
handle the result.
📌 Example: Fetching Data
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json()) // Convert response to JSON
.then((data) => console.log(data)) // Use the data
.catch((error) => console.error("Error:", error));
✅ Output
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
📌 Explanation
1. fetch("URL") sends a request to get data.
Asynchronous Programming 12
2. .then(response => response.json()) converts the response to JavaScript.
3. .then(data => console.log(data)) prints the data.
4. .catch(error => console.error(error)) handles errors.
6️⃣ resolve() vs reject() vs .then() vs .catch()
Function Purpose
resolve(value) Marks a promise as successful and sends value .
reject(error) Marks a promise as failed and sends error .
.then(successFn) Runs when promise is resolved.
.catch(errorFn) Runs when promise is rejected.
7️⃣ Stopping a Request (Abort a Fetch)
If a request takes too long, we can cancel it.
📌 Example:
const controller = new AbortController();
const signal = controller.signal;
fetch("https://jsonplaceholder.typicode.com/todos/1", { signal })
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Fetch aborted:", error));
// Stop the request after 1 second
setTimeout(() => {
controller.abort();
console.log("Request Aborted!");
}, 1000);
✅ Explanation
controller.abort() stops the request if it takes too long.
Asynchronous Programming 13
If stopped, .catch() runs.
8️⃣ Understanding .json() and .text()
After fetching, we convert the response.
Method Converts To Example
.json() JavaScript Object API responses
.text() Plain text Simple text files
📌 Example: Using .json()
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json())
.then((data) => console.log(data));
✅ Output
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }
📌 Example: Using .text()
fetch("https://example.com/file.txt")
.then((response) => response.text())
.then((data) => console.log(data));
✅ Output
Hello, this is a text file!
9️⃣ Status Codes & Headers
When making a request, the server sends a status code.
Code Meaning
Asynchronous Programming 14
200 ✅ Success
201 ✅ Created
400 ❌ Bad Request
401 ❌ Unauthorized
404 ❌ Not Found
500 ❌ Server Error
📌 Example: Checking Status
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => {
if (!response.ok) {
throw new Error(`Error: ${response.status} - ${response.statusText}`);
}
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error(error));
✅ Explanation
response.ok checks if status is 200-299.
response.status gives the status code.
response.statusText gives a short message.
🔟 Final Recap
1️⃣ Promises help with tasks that take time.
2️⃣ /
resolve() control success/failure.
reject()
3️⃣ handles success,
.then() handles failure.
.catch()
4️⃣ Fetch API uses promises to get data.
5️⃣ vs converts responses.
.json() .text()
6️⃣ Stopping requests is done using .AbortController()
Asynchronous Programming 15
7️⃣ Status codes tell us if the request was successful or failed.
1️⃣ What is fetch() ?
is a function in JavaScript that is used to make HTTP requests (like getting
fetch()
data from a website or API).
📌 Think of fetch() as ordering food online 🍕
You place an order ( fetch() )
The restaurant processes your request (API works in the background)
You get a delivery (the response from the server)
You open the package and check your food (process the response)
2️⃣ Example: Fetching Data from an API
Let's see how fetch() works:
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json()) // Convert response to JSON
.then((data) => console.log(data)) // Print data
.catch((error) => console.error("Error:", error)); // Handle errors
Step-by-Step Breakdown
1️⃣ sends a request to the server.
fetch("URL")
2️⃣ The server sends a response ( object)
response
3️⃣ We convert the response to JSON ( response.json() )
4️⃣ We handle the data in .then((data) => console.log(data))
5️⃣ If there’s an error, will handle it
.catch()
3️⃣ What is an HTTP Response Object?
Asynchronous Programming 16
When we call fetch() , it returns a response object that contains details about the
server’s reply.
Example of an HTTP Response object:
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log(response); // See all response details
});
Important Properties of response
Property Meaning
response.ok true if request was successful (status code 200–299)
response.status HTTP status code (e.g., 200 = OK, 404 = Not Found)
response.statusText Text description of the status (e.g., "OK", "Not Found")
response.headers Headers sent by the server
response.url The URL of the fetched resource
response.json() Converts response to JSON (if applicable)
response.text() Reads response as raw text
4️⃣ What Are HTTP Status Codes?
When we make a request, the server responds with a status code that tells us
what happened.
📌 Think of HTTP status codes like restaurant order statuses
→ Order is ready 🍕
200 OK
→ Restaurant doesn’t have that item ❌
404 Not Found
→ Kitchen is broken 🚨
500 Internal Server Error
Common Status Codes
Code Meaning Example
Asynchronous Programming 17
200 OK ✅ Data was fetched successfully
201 Created 🆕 A new resource was created (like posting a new
blog)
400 Bad Request ❌ Something is wrong with the request
401 Unauthorized 🔒 You need to log in first
403 Forbidden 🚫 You don’t have permission
404 Not Found ❌ The page or resource doesn’t exist
Internal Server Error
500
🔥 Something is broken on the server
Example: Checking Status Code
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log("Status:", response.status); // e.g., 200
console.log("Status Text:", response.statusText); // e.g., "OK"
});
5️⃣ Understanding .json() , .text() , and Headers
🟢 .json() - Convert Response to JSON
If the response is in JSON format, we use response.json() :
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json()) // Convert response to JSON
.then((data) => console.log(data)); // Output the JSON data
✅ Example JSON Output:
{
"userId": 1,
"id": 1,
"title": "Sample Post",
Asynchronous Programming 18
"body": "This is an example blog post."
}
🟡 .text() - Read Response as Plain Text
If the response is not JSON, we use response.text() :
fetch("https://www.example.com")
.then((response) => response.text()) // Read response as text
.then((data) => console.log(data)); // Output the text content
✅ Example Output:
<html>
<head><title>Example</title></head>
<body>Welcome to my site!</body>
</html>
🔵 response.headers - Get Headers
Headers contain extra information about the response.
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => {
console.log(response.headers);
});
✅ Example Output:
Headers { "content-type": "application/json; charset=utf-8" }
6️⃣ How to Stop a Request?
Sometimes, we may want to cancel a request before it completes.
Asynchronous Programming 19
We can use an AbortController for this.
Example: Cancel a Request After 1 Second
const controller = new AbortController();
const signal = controller.signal;
fetch("https://jsonplaceholder.typicode.com/posts/1", { signal })
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.log("Request canceled:", error.message));
setTimeout(() => controller.abort(), 1000); // Cancel after 1 second
Final Recap
Concept Meaning
fetch("URL") Makes a request to a server
response.ok true if request was successful
response.status HTTP status code (200, 404, 500, etc.)
response.statusText Describes the status (e.g., "OK", "Not Found")
response.json() Converts response to JSON
response.text() Converts response to plain text
response.headers Returns response headers
.catch() Handles errors
AbortController Cancels a request
🔥 Quick Summary
1️⃣ is used to request data from a server.
fetch()
2️⃣ The response object contains details like status, headers, and content.
3️⃣ Use to convert JSON data and for plain text responses.
.json() .text()
Asynchronous Programming 20
4️⃣ Check response.status for status codes (200 OK, 404 Not Found, etc.).
5️⃣ Use AbortController to stop a request.
Sai, does this all make sense? 😃
If anything is still confusing, let me know, and I'll simplify it even more! 🚀
Asynchronous Programming 21