Assignments
of Day 15: Asynchronous JavaScript
These
assignments will help you understand and practice the key concepts of Callbacks,
Promises, and Async/Await in JavaScript.
Assignment
1: Using Callbacks for Asynchronous Operations
Task:
Write a
function getUserData(callback) that simulates an asynchronous operation of
fetching user data. The function should use setTimeout to simulate a 2-second
delay before invoking the callback function with some sample user data.
Then,
write a handleUserData() function to process the user data returned by
getUserData().
Steps:
1. Create a
function getUserData(callback) that simulates fetching user data.
2. Call
getUserData() and pass the handleUserData function as the callback.
3. Display
the processed data in handleUserData().
javascript
Copy code
// Step 1: Function to simulate fetching user data
asynchronously using setTimeout
function getUserData(callback) {
setTimeout(() => {
const
user = { name: "Alice", age: 25, country: "USA" };
console.log("User data fetched!");
callback(user); // Step 2: Passing the user data to the callback
}, 2000);
// Simulating a 2-second delay
}
// Step 2: Function to handle the fetched data
function handleUserData(user) {
console.log(`Name: ${user.name}`);
console.log(`Age: ${user.age}`);
console.log(`Country: ${user.country}`);
}
// Step 3: Call the getUserData function with the
handleUserData callback
getUserData(handleUserData);
Explanation:
- The
getUserData() function simulates a delay using setTimeout() and then calls
the callback function (handleUserData()) with the user data after 2
seconds.
- handleUserData()
is the callback that processes and prints the user data.
Assignment
2: Converting Callbacks to Promises
Task:
Rewrite
the getUserData() function from Assignment 1 to use a Promise instead of a
callback.
Steps:
1. Replace
the callback mechanism with a Promise.
2. Use
.then() and .catch() to handle the result and errors.
javascript
Copy code
// Step 1: Modify getUserData to return a promise
function getUserData() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Bob", age: 30, country: "UK" };
console.log("User data fetched!");
resolve(user); // Resolving the promise with user data
}, 2000);
// Simulating a 2-second delay
});
}
// Step 2: Using the promise with .then() and
.catch()
getUserData()
.then(user
=> {
console.log(`Name: ${user.name}`);
console.log(`Age: ${user.age}`);
console.log(`Country: ${user.country}`);
})
.catch(error => {
console.log("Error:", error);
});
Explanation:
- Instead
of using callbacks, the getUserData() function returns a Promise.
- The
.then() method handles the resolved value (user data), and .catch() is
used to handle any errors that might occur.
Assignment
3: Using Promise Chaining
Task:
Create a
series of asynchronous tasks using promises. The tasks are as follows:
1. Fetch
user data (using a promise).
2. Update
the user's age.
3. Save the
updated user data.
Use
promise chaining to execute these tasks in sequence.
Steps:
1. Create a
promise to fetch the user data.
2. Chain
.then() to update the age.
3. Chain
another .then() to save the updated data.
javascript
Copy code
// Step 1: Promise to fetch user data
function getUserData() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Charlie", age: 35, country: "Canada" };
console.log("User data fetched!");
resolve(user); // Resolving the promise with user data
}, 2000);
});
}
// Step 2: Promise to update the user's age
function updateUserAge(user, newAge) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
user.age = newAge;
console.log("User age updated!");
resolve(user); // Resolving with updated user data
}, 1000);
});
}
// Step 3: Promise to save the updated user data
function saveUserData(user) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
console.log("User data saved!");
resolve(user); // Resolving with the saved user data
}, 1000);
});
}
// Step 4: Chain the promises to perform the tasks
sequentially
getUserData()
.then(user
=> updateUserAge(user, 40)) // Updating the user's age
.then(updatedUser => saveUserData(updatedUser)) // Saving the updated
data
.then(finalUser => {
console.log(`Final User: ${JSON.stringify(finalUser)}`);
})
.catch(error => {
console.log("Error:", error);
});
Explanation:
- We
chain promises using .then() to ensure that each task is completed before
the next one begins.
- The
user data is fetched, updated, and then saved sequentially.
Assignment
4: Using Async/Await for Cleaner Code
Task:
Rewrite
the promise chaining from Assignment 3 using async/await syntax for a cleaner,
more synchronous-like flow.
Steps:
1. Create an
async function.
2. Use await
to pause the execution until the promise resolves.
3. Handle
errors using try...catch.
javascript
Copy code
// Step 1: Modify functions to return promises
(same as previous assignment)
function getUserData() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "David", age: 28, country: "Australia" };
console.log("User data fetched!");
resolve(user);
}, 2000);
});
}
function updateUserAge(user, newAge) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
user.age = newAge;
console.log("User age updated!");
resolve(user);
}, 1000);
});
}
function saveUserData(user) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
console.log("User data saved!");
resolve(user);
}, 1000);
});
}
// Step 2: Create an async function to handle the
operations
async function performUserTasks() {
try {
const
user = await getUserData(); // Wait for user data
const
updatedUser = await updateUserAge(user, 45); // Wait for the updated user data
const
savedUser = await saveUserData(updatedUser); // Wait for saving the user data
console.log(`Final User: ${JSON.stringify(savedUser)}`);
} catch
(error) {
console.log("Error:", error);
}
}
// Step 3: Call the async function
performUserTasks();
Explanation:
- The
performUserTasks function is declared as async, allowing us to use await
for each promise.
- await
pauses the execution until each promise resolves, making the flow of code
easier to follow, compared to the .then() method.
Assignment
5: Error Handling with Async/Await
Task:
Write an
async function to fetch data from a simulated API, process it, and handle
errors appropriately using try...catch.
Steps:
1. Use
async/await to fetch data.
2. Use
try...catch for error handling.
javascript
Copy code
// Simulating an API call using a promise
function fetchDataFromAPI() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
success = true; // Change to false to simulate an error
if
(success) {
resolve("Data fetched successfully!");
} else
{
reject("Failed to fetch data.");
}
}, 2000);
});
}
// Async function to fetch and process data
async function getProcessedData() {
try {
const
data = await fetchDataFromAPI(); // Await the promise
console.log(data);
console.log("Processing data...");
//
Simulating data processing
} catch
(error) {
console.log("Error:", error); // Catching any errors that
occur
}
}
// Calling the async function
getProcessedData();
Explanation:
- The
fetchDataFromAPI() function simulates a successful or failed API call.
- The
getProcessedData() function is async, and inside it, we use await to
handle the promise and try...catch to handle errors.
Conclusion:
By
completing these assignments, you will gain a strong understanding of
asynchronous JavaScript and be comfortable with using callbacks, promises, and
async/await for managing asynchronous operations in your code.
4o mini
You said:
give some
more to understand well
ChatGPT
said:
ChatGPT
Here are
additional assignments to help you gain a deeper understanding of Asynchronous
JavaScript concepts, focusing on Callbacks, Promises, and Async/Await.
These exercises will provide more practical applications and scenarios for you
to explore.
Assignment
6: Simulating a Database Fetch Operation (Callbacks)
Task:
Simulate
a database fetch operation using a callback. The function should return a list
of users after a 2-second delay. You need to process this list in the callback
function.
Steps:
1. Create a
function fetchDatabase(callback) that simulates a fetch operation with
setTimeout.
2. Process
the data inside the callback.
javascript
Copy code
// Simulating a database fetch operation
function fetchDatabase(callback) {
setTimeout(() => {
const
users = [
{ name:
"John", age: 28 },
{ name:
"Jane", age: 34 },
{ name:
"Alice", age: 22 }
];
console.log("Database fetched!");
callback(users); // Passing the fetched data to the callback
}, 2000);
}
// Process the data in a callback
function processUserData(users) {
users.forEach(user => {
console.log(`Name: ${user.name}, Age: ${user.age}`);
});
}
// Calling fetchDatabase with a callback
fetchDatabase(processUserData);
Explanation:
- fetchDatabase()
simulates a database fetch and uses a callback to pass the data.
- The
processUserData() function is the callback that processes the list of
users.
Assignment
7: Promise Chaining with Multiple Steps
Task:
You have
three asynchronous tasks:
1. Fetch a
user's details.
2. Fetch
their order history.
3. Fetch the
shipping status of their last order.
Use
promises and chain these tasks in sequence.
Steps:
1. Create
promises to fetch user details, order history, and shipping status.
2. Chain
these promises using .then().
javascript
Copy code
// Fetch user details
function fetchUserDetails() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Bob", id: 1 };
console.log("User details fetched!");
resolve(user); // Resolving with user details
}, 1000);
});
}
// Fetch order history
function fetchOrderHistory(userId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
orders = [
{
orderId: 101, status: "shipped" },
{
orderId: 102, status: "pending" }
];
console.log("Order history fetched!");
resolve(orders); // Resolving with order details
}, 1000);
});
}
// Fetch shipping status
function fetchShippingStatus(orderId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
status = "shipped";
console.log("Shipping status fetched!");
resolve(status); // Resolving with shipping status
}, 1000);
});
}
// Chain the promises
fetchUserDetails()
.then(user
=> fetchOrderHistory(user.id))
.then(orders => fetchShippingStatus(orders[0].orderId))
.then(status => console.log(`Last order shipping status: ${status}`))
.catch(error => console.log("Error:", error));
Explanation:
- Each
task is wrapped in a promise.
- The
tasks are chained using .then() to execute them in sequence.
- Errors
are caught in the .catch() block.
Assignment
8: Using Async/Await with Multiple API Calls
Task:
Rewrite
the sequence of asynchronous tasks from Assignment 7 using async/await. The
goal is to fetch user details, order history, and shipping status, then log the
final status.
Steps:
1. Use
async/await to fetch the user details, order history, and shipping status.
2. Use
try...catch for error handling.
javascript
Copy code
// Simulate fetching user details
function fetchUserDetails() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Sam", id: 2 };
resolve(user);
}, 1000);
});
}
// Simulate fetching order history
function fetchOrderHistory(userId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
orders = [
{
orderId: 103, status: "shipped" },
{
orderId: 104, status: "pending" }
];
resolve(orders);
}, 1000);
});
}
// Simulate fetching shipping status
function fetchShippingStatus(orderId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
status = "pending";
resolve(status);
}, 1000);
});
}
// Async function using await to handle tasks
sequentially
async function getShippingStatus() {
try {
const
user = await fetchUserDetails(); // Await for user details
const
orders = await fetchOrderHistory(user.id); // Await for orders
const
status = await fetchShippingStatus(orders[0].orderId); // Await for shipping
status
console.log(`Last order shipping status: ${status}`);
} catch
(error) {
console.log("Error:", error);
}
}
// Call the async function
getShippingStatus();
Explanation:
- async
function getShippingStatus() handles asynchronous tasks with await.
- The
code is cleaner and easier to follow compared to promise chaining.
Assignment
9: Simulating an API Error Handling with Async/Await
Task:
Simulate
an error while fetching the shipping status. Modify the fetchShippingStatus
function to reject the promise if the order is "pending". Handle the
error gracefully in the async function.
Steps:
1. Modify
fetchShippingStatus to reject a promise for pending orders.
2. Use
try...catch to handle errors in the async function.
javascript
Copy code
// Simulate fetching user details
function fetchUserDetails() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Mike", id: 3 };
resolve(user);
}, 1000);
});
}
// Simulate fetching order history
function fetchOrderHistory(userId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
orders = [
{
orderId: 105, status: "shipped" },
{
orderId: 106, status: "pending" }
];
resolve(orders);
}, 1000);
});
}
// Simulate fetching shipping status with potential
rejection
function fetchShippingStatus(orderId) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
status = "pending"; // Simulate an issue with pending status
if
(status === "pending") {
reject("Shipping status is pending. Cannot proceed.");
} else
{
resolve(status);
}
}, 1000);
});
}
// Async function to handle the sequence with error
handling
async function getShippingStatus() {
try {
const
user = await fetchUserDetails(); // Await for user details
const
orders = await fetchOrderHistory(user.id); // Await for orders
const
status = await fetchShippingStatus(orders[1].orderId); // This will throw error
as status is pending
console.log(`Last order shipping status: ${status}`);
} catch
(error) {
console.log("Error:", error); // Handle error
}
}
// Call the async function
getShippingStatus();
Explanation:
- fetchShippingStatus()
has been modified to simulate an error when the shipping status is
"pending".
- The
error is caught in the catch block and logged.
Assignment
10: Simulating a Timeout in Async/Await
Task:
Simulate
a timeout in the asynchronous operation by rejecting the promise if the
operation takes too long. Use async/await to manage this.
Steps:
1. Modify
the fetchUserDetails function to reject after a timeout.
2. Handle
the timeout error gracefully with try...catch.
javascript
Copy code
// Simulating a delayed fetch operation with
timeout
function fetchUserDetails() {
return new
Promise((resolve, reject) => {
setTimeout(() => {
const
user = { name: "Tom", id: 4 };
reject("Timeout: Data fetch took too long.");
}, 5000);
// Reject after 5 seconds to simulate a timeout
});
}
// Async function to handle the fetch with timeout
async function getUserDataWithTimeout() {
try {
const
user = await fetchUserDetails();
console.log(`User: ${user.name}`);
} catch
(error) {
console.log("Error:", error); // Catch timeout error
}
}
// Call the async function
getUserDataWithTimeout();
Explanation:
- The
fetchUserDetails() function simulates a delay and rejects the promise
after 5 seconds, simulating a timeout.
- The
error is caught in the catch block and handled accordingly.
Conclusion:
These
additional assignments provide more complex scenarios and practical use cases
of Callbacks, Promises, and Async/Await. By practicing
these, you'll develop a deeper understanding of how to handle asynchronous
operations, error handling, and the benefits of each approach in real-world
JavaScript applications.
4o mini
You said:
give some
more to understand this concept well as i am the beginner
ChatGPT
said:
ChatGPT
Here are
additional assignments with a focus on Asynchronous JavaScript, designed
to help you deepen your understanding as a beginner. These exercises will
provide more hands-on practice with callbacks, promises, and async/await.
Assignment
11: Simple Callback Function
Task:
Create a
simple callback function that simulates a user login process. The function
should return the login status after a 1-second delay.
Steps:
1. Create a
function userLogin that simulates a login process.
2. Use a
callback to display the login success or failure message.
javascript
Copy code
// Simulate a user login process
function userLogin(username, password, callback) {
setTimeout(() => {
if
(username === "user" && password === "pass") {
callback(null, "Login successful!"); // Success
} else {
callback("Login failed. Please check your credentials.",
null); // Failure
}
}, 1000);
}
// Process the login result in a callback
function handleLoginResult(error, message) {
if (error)
{
console.log(error);
} else {
console.log(message);
}
}
// Call the login function with a callback
userLogin("user", "pass",
handleLoginResult);
Explanation:
- The userLogin()
function simulates a login operation with a 1-second delay.
- A
callback function handleLoginResult() processes the login result.
Assignment
12: Promises with Success and Failure
Task:
Create a
promise that resolves if the user is logged in, and rejects if the login fails.
Handle both cases using .then() and .catch().
Steps:
1. Create a
promise for the login process.
2. Handle
success and failure using .then() and .catch().
javascript
Copy code
// Simulate a login process returning a promise
function login(username, password) {
return new
Promise((resolve, reject) => {
setTimeout(() => {
if
(username === "admin" && password === "admin123") {
resolve("Login successful!"); // Resolve on success
} else
{
reject("Login failed. Incorrect credentials."); // Reject on
failure
}
}, 1000);
});
}
// Use the promise to handle success and failure
login("admin", "admin123")
.then((message) => console.log(message))
.catch((error) => console.log(error));
Explanation:
- The
login() function returns a promise that resolves or rejects based on the
login credentials.
- The
.then() block processes the success, and the .catch() block handles the
error.
Assignment
13: Promise Chaining
Task:
Use
promise chaining to simulate fetching user data, followed by fetching their
orders, and finally fetching their order status.
Steps:
1. Create
promises for user data, orders, and order status.
2. Chain the
promises using .then().
javascript
Copy code
// Fetch user details
function getUserDetails() {
return new
Promise((resolve) => {
setTimeout(() => {
const
user = { id: 1, name: "Alice" };
resolve(user);
}, 1000);
});
}
// Fetch user orders
function getUserOrders(userId) {
return new
Promise((resolve) => {
setTimeout(() => {
const
orders = [{ orderId: 101, status: "shipped" }];
resolve(orders);
}, 1000);
});
}
// Fetch order status
function getOrderStatus(orderId) {
return new
Promise((resolve) => {
setTimeout(() => {
const
status = "shipped";
resolve(status);
}, 1000);
});
}
// Chain promises
getUserDetails()
.then((user) => {
console.log(`User: ${user.name}`);
return
getUserOrders(user.id); // Fetch orders
})
.then((orders) => {
console.log("Orders:", orders);
return
getOrderStatus(orders[0].orderId); // Fetch order status
})
.then((status) => {
console.log(`Order status: ${status}`);
})
.catch((error) => console.log("Error:", error));
Explanation:
- The
promises are chained one after the other. Each .then() processes the
result from the previous promise and passes the value to the next
function.
Assignment
14: Using Async/Await for Sequential Tasks
Task:
Use
async/await to fetch user details, their orders, and the order status in a
sequential manner.
Steps:
1. Use
async/await to handle the tasks in a sequence.
2. Handle
any errors that may occur.
javascript
Copy code
// Fetch user details
function getUserDetails() {
return new
Promise((resolve) => {
setTimeout(() => {
const
user = { id: 1, name: "Bob" };
resolve(user);
}, 1000);
});
}
// Fetch user orders
function getUserOrders(userId) {
return new
Promise((resolve) => {
setTimeout(() => {
const
orders = [{ orderId: 102, status: "pending" }];
resolve(orders);
}, 1000);
});
}
// Fetch order status
function getOrderStatus(orderId) {
return new
Promise((resolve) => {
setTimeout(() => {
const
status = "pending";
resolve(status);
}, 1000);
});
}
// Async function using await
async function getOrderInfo() {
try {
const
user = await getUserDetails();
console.log(`User: ${user.name}`);
const
orders = await getUserOrders(user.id);
console.log("Orders:", orders);
const
status = await getOrderStatus(orders[0].orderId);
console.log(`Order status: ${status}`);
} catch
(error) {
console.log("Error:", error);
}
}
// Call the async function
getOrderInfo();
Explanation:
- The
async function getOrderInfo() handles each asynchronous task sequentially
with await.
- Errors
are caught with try...catch to handle exceptions.
Assignment
15: Handling Multiple Asynchronous Tasks with Async/Await
Task:
Fetch the
user details and order history simultaneously (in parallel) using async/await.
Use Promise.all() to handle multiple promises at once.
Steps:
1. Use
Promise.all() to fetch user details and orders in parallel.
2. Await
both tasks and display the results.
javascript
Copy code
// Simulate fetching user details
function getUserDetails() {
return new
Promise((resolve) => {
setTimeout(() => {
const
user = { id: 2, name: "Charlie" };
resolve(user);
}, 1000);
});
}
// Simulate fetching order history
function getOrderHistory() {
return new
Promise((resolve) => {
setTimeout(() => {
const
orders = [
{
orderId: 201, status: "delivered" },
{
orderId: 202, status: "shipped" }
];
resolve(orders);
}, 1000);
});
}
// Async function to fetch both user details and
order history
async function fetchUserAndOrders() {
try {
const
[user, orders] = await Promise.all([getUserDetails(), getOrderHistory()]);
console.log(`User: ${user.name}`);
console.log("Orders:", orders);
} catch
(error) {
console.log("Error:", error);
}
}
// Call the async function
fetchUserAndOrders();
Explanation:
- Promise.all()
is used to fetch both user details and order history simultaneously.
- The
results are awaited, and once both promises resolve, their results are
processed.
Assignment
16: Simulating Delayed API Response
Task:
Simulate
an API call with a delayed response. Use async/await to manage the delayed
response and handle the result.
Steps:
1. Simulate
a delayed response using setTimeout.
2. Use
async/await to handle the delay.
javascript
Copy code
// Simulate a delayed API call
function apiCall() {
return new
Promise((resolve) => {
setTimeout(() => {
resolve("API call completed!");
}, 3000);
// 3-second delay
});
}
// Async function to handle delayed response
async function fetchApiData() {
console.log("Fetching data...");
const
response = await apiCall(); // Await the API call
console.log(response); // Log the response after 3 seconds
}
// Call the async function
fetchApiData();
Explanation:
- The
apiCall() function simulates an API call with a 3-second delay using
setTimeout.
- async/await
is used to wait for the result before proceeding.
Conclusion:
These
assignments build upon the concepts of callbacks, promises, and async/await,
helping you get hands-on practice with asynchronous JavaScript. By solving
these problems, you will better understand how JavaScript handles asynchronous
operations, how to manage multiple tasks, and how to handle errors effectively.
Keep practicing these concepts to improve your understanding and skills!
4o mini
You said:
