javascriptadvanced15 minutes

Refactor Nested Callbacks to Async/Await for Cleaner Asynchronous Code

Improve the provided JavaScript function by refactoring deeply nested callbacks into a more readable and maintainable async/await structure without changing the current functionality.

Challenge prompt

You are given a function that performs multiple asynchronous database calls using nested callbacks. This causes callback hell and makes the code hard to read and maintain. Refactor this function to use async/await syntax while preserving the original behavior and error handling. The function fetches user data from three sequential API endpoints, where each call depends on the previous call's result. Ensure all errors are properly propagated and caught, maintaining the original logical flow without introducing side effects.

Guidance

  • Convert callback-based asynchronous functions into Promises if they are not already Promise-based.
  • Use async/await to flatten the nested callbacks and improve readability.
  • Maintain the original error handling logic using try/catch blocks.

Hints

  • Look for places where functions accept callbacks and consider wrapping them with util.promisify or manually creating Promises.
  • Remember that async functions always return a Promise; use await to pause execution until each Promise resolves.
  • Keep the logical order of operations the same while refactoring.

Starter code

function getUserProfile(userId, callback) {
  getUser(userId, function(err, user) {
    if (err) return callback(err);
    getPosts(user.id, function(err, posts) {
      if (err) return callback(err);
      getComments(posts[0].id, function(err, comments) {
        if (err) return callback(err);
        callback(null, { user, posts, comments });
      });
    });
  });
}

// Dummy async functions
function getUser(id, cb) {
  setTimeout(() => cb(null, { id, name: 'Alice' }), 100);
}

function getPosts(userId, cb) {
  setTimeout(() => cb(null, [{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }]), 100);
}

function getComments(postId, cb) {
  setTimeout(() => cb(null, ['Nice post!', 'Thanks for sharing']), 100);
}

Expected output

{ user: { id: userId, name: 'Alice' }, posts: [ { id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' } ], comments: [ 'Nice post!', 'Thanks for sharing' ] }

Core concepts

async/awaitcallback hellerror handlingpromises

Challenge a Friend

Send this duel to someone else and see if they can solve it.