From Promise to async/await


Limitations of Promises

Promises, introduced in ES6, helped solve callback hell and systematized asynchronous processing, but still had limitations when handling complex asynchronous logic:

  • Reduced readability due to continuous chaining of then methods
  • Difficulty tracking code in complex asynchronous flows
  • Scattered error handling logic

The Emergence of async/await (ES7)

To overcome these limitations of Promises, async/await was introduced in ES7. This allowed developers to write asynchronous code as if it were synchronous.

Code Comparison Example

// 1. Asynchronous processing using Promise
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true;
      if (success) resolve('Data fetching successful');
      else reject('Error occurred!');
    }, 1000);
  });
};

// Promise chaining approach
fetchData()
  .then((data) => {
    console.log(data);
    return 'Proceeding to next step';
  })
  .then((nextStep) => {
    console.log(nextStep);
  })
  .catch((error) => {
    console.error(error);
  });

// 2. Asynchronous processing using async/await
const fetchDataAsync = async () => {
  try {
    const data = await fetchData();
    console.log(data);    
    const nextStep = 'Proceeding to next step';
    console.log(nextStep);
  } catch (error) {
    console.error(error);  
  }
};

fetchDataAsync();

Advantages of async/await

  1. Improved Readability

    • Code reads sequentially from top to bottom
    • Ability to write asynchronous logic like synchronous code
  2. Better Error Handling

    • Unified error handling through try-catch blocks
    • Standardized approach for both synchronous and asynchronous error handling
  3. Enhanced Debugging

    • Easier to set breakpoints
    • Simpler to trace code execution flow