17.4 Homework Assignment (15 mins)

Objective:

Students will apply the concepts of asynchronous programming, including callbacks, promises, and async/await, to simulate real-world tasks. This assignment reinforces the topics covered in the lecture and programming activities.


Assignment Task:

  1. Create a JavaScript program that simulates the following sequence of asynchronous tasks:

    • Fetch user profile (Simulate fetching a user profile with a delay).

    • Fetch user posts (Simulate fetching a user's posts after the profile is fetched).

    • Fetch user comments (Simulate fetching comments for a specific post).

  2. Implement the solution using:

    • Callbacks

    • Promises

    • Async/Await


Step-by-Step Procedure for Programming Activity

1. Setup the Asynchronous Tasks

Simulate the following functions using setTimeout:

  • fetchUserProfile: Resolves after 1 second with a user object.

  • fetchUserPosts: Resolves after 2 seconds with an array of posts for the user.

  • fetchPostComments: Resolves after 1.5 seconds with an array of comments for a post.

function fetchUserProfile(callback) {
  setTimeout(() => {
    callback(null, { id: 1, name: 'Alice' });
  }, 1000);
}

function fetchUserPosts(userId, callback) {
  setTimeout(() => {
    if (userId !== 1) {
      callback('User not found', null);
    } else {
      callback(null, ['Post 1', 'Post 2']);
    }
  }, 2000);
}

function fetchPostComments(post, callback) {
  setTimeout(() => {
    callback(null, [`Comment for ${post}`]);
  }, 1500);
}

2. Task 1: Implement Using Callbacks

Use nested callbacks to execute the tasks sequentially:

  1. Fetch the user profile.

  2. Fetch posts for the user.

  3. Fetch comments for the first post.

Solution:

fetchUserProfile((err, user) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(`User: ${user.name}`);
  fetchUserPosts(user.id, (err, posts) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log(`Posts: ${posts}`);
    fetchPostComments(posts[0], (err, comments) => {
      if (err) {
        console.error(err);
        return;
      }
      console.log(`Comments for ${posts[0]}: ${comments}`);
    });
  });
});

3. Task 2: Refactor Using Promises

Modify the task functions to return promises instead of accepting callbacks:

function fetchUserProfile() {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ id: 1, name: 'Alice' }), 1000);
  });
}

function fetchUserPosts(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (userId !== 1) {
        reject('User not found');
      } else {
        resolve(['Post 1', 'Post 2']);
      }
    }, 2000);
  });
}

function fetchPostComments(post) {
  return new Promise((resolve) => {
    setTimeout(() => resolve([`Comment for ${post}`]), 1500);
  });
}

Solution Using Promises:

fetchUserProfile()
  .then((user) => {
    console.log(`User: ${user.name}`);
    return fetchUserPosts(user.id);
  })
  .then((posts) => {
    console.log(`Posts: ${posts}`);
    return fetchPostComments(posts[0]);
  })
  .then((comments) => {
    console.log(`Comments for Post 1: ${comments}`);
  })
  .catch((err) => {
    console.error(err);
  });

4. Task 3: Refactor Using Async/Await

Use async/await to make the program more readable:

  1. Create an async function to execute the tasks sequentially.

  2. Use try...catch for error handling.

Solution Using Async/Await:

async function displayUserData() {
  try {
    const user = await fetchUserProfile();
    console.log(`User: ${user.name}`);

    const posts = await fetchUserPosts(user.id);
    console.log(`Posts: ${posts}`);

    const comments = await fetchPostComments(posts[0]);
    console.log(`Comments for Post 1: ${comments}`);
  } catch (err) {
    console.error(err);
  }
}

displayUserData();

Assignment Deliverables:

  • A single JavaScript file (asynchronous.js) containing:

    1. The callback-based implementation.

    2. The promise-based implementation.

    3. The async/await implementation.


Expected Outcomes:

  1. Students will learn to handle asynchronous tasks sequentially using different techniques.

  2. They will compare and contrast callbacks, promises, and async/await in terms of readability and error handling.

  3. Gain hands-on experience in refactoring code for improved maintainability.

Last updated