javascriptadvanced15 minutes

Refactor Complex Nested Callback Code to Async/Await in JavaScript

Improve code quality by refactoring a deeply nested callback-based asynchronous function into a clean, readable async/await structure, while maintaining identical functionality.

Challenge prompt

You are given a JavaScript function that performs multiple asynchronous database fetches using nested callbacks, resulting in complex callback hell. Your task is to refactor this function into a clean async/await implementation without changing its behavior or output. Ensure proper error handling and maintain the logical order of asynchronous calls.

Guidance

  • Convert callback-based functions into promises or use promisified versions.
  • Use async/await to linearize asynchronous logic and avoid deeply nested callbacks.
  • Keep the error handling intact by using try/catch blocks.
  • Preserve the original data flow and output format.

Hints

  • Wrap each asynchronous call that uses callbacks into a promise if it doesn't already return one.
  • Remember that async functions always return promises, which you can await sequentially.
  • Pay attention to where errors are handled and replicate that behavior with try/catch.

Starter code

function fetchUserData(userId, callback) {
  getUser(userId, function(err, user) {
    if (err) return callback(err);
    getUserPosts(user.id, function(err, posts) {
      if (err) return callback(err);
      getCommentsForPosts(posts, function(err, comments) {
        if (err) return callback(err);
        callback(null, { user, posts, comments });
      });
    });
  });
}

// Simulated async functions
function getUser(id, cb) {
  setTimeout(() => cb(null, { id, name: 'Alice' }), 100);
}
function getUserPosts(userId, cb) {
  setTimeout(() => cb(null, [{ id: 1, content: 'Hello World' }, { id: 2, content: 'Another post' }]), 100);
}
function getCommentsForPosts(posts, cb) {
  setTimeout(() => cb(null, [{ postId: 1, text: 'Nice post!' }, { postId: 2, text: 'Thanks for sharing' }]), 100);
}

Expected output

{ user: { id: 1, name: 'Alice' }, posts: [{ id: 1, content: 'Hello World' }, { id: 2, content: 'Another post' }], comments: [{ postId: 1, text: 'Nice post!' }, { postId: 2, text: 'Thanks for sharing' }] }

Core concepts

async/awaitcallback hellpromiseserror handling

Challenge a Friend

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