Skip to content
intermediatePhase 33 · Advanced JavaScript

Async / Await

Write asynchronous code with async/await syntax and error handling.

45m
0 problems
Topic Progress0%

Async Functions

The async keyword declares a function that always returns a Promise. It allows you to write async code that looks synchronous.

Basic Syntax

async function fetchData() {
  return 'Hello'; // Automatically wrapped in Promise
}

fetchData().then(result => console.log(result)); // 'Hello'

Why Use Async?

Without async/await:

function getUser() {
  return fetch('/api/user')
    .then(response => response.json())
    .then(user => {
      return fetch(`/api/posts/${user.id}`);
    })
    .then(response => response.json())
    .then(posts => {
      console.log(posts);
    });
}

With async/await:

async function getUser() {
  const response = await fetch('/api/user');
  const user = await response.json();
  const postsResponse = await fetch(`/api/posts/${user.id}`);
  const posts = await postsResponse.json();
  console.log(posts);
}

Arrow Functions

const getData = async () => {
  const data = await fetch('/api/data');
  return data.json();
};

Top-Level Await

// In ES modules, you can use await at the top level
const response = await fetch('/api/config');
const config = await response.json();
export default config;

Await Syntax

The await keyword pauses the async function execution until the Promise settles.

How Await Works

async function example() {
  console.log('Start');
  
  const result = await Promise.resolve('done');
  // Execution pauses here until promise resolves
  
  console.log(result); // 'done'
  console.log('End');
}

example();
// Output:
// Start
// done
// End

Await with Real Promises

async function fetchUserData() {
  // Await pauses until fetch completes
  const response = await fetch('/api/user');
  
  // Check response
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  
  // Await pauses until JSON parsing completes
  const user = await response.json();
  
  return user;
}

Parallel Operations

// BAD - sequential (slower)
async function getData() {
  const users = await fetch('/api/users');
  const posts = await fetch('/api/posts'); // Waits for users first
  return { users, posts };
}

// GOOD - parallel (faster)
async function getData() {
  const [users, posts] = await Promise.all([
    fetch('/api/users'),
    fetch('/api/posts')
  ]);
  return { users, posts };
}

Await in Loops

// Sequential processing
async function processItems(items) {
  const results = [];
  for (const item of items) {
    const result = await processItem(item);
    results.push(result);
  }
  return results;
}

// Parallel processing
async function processItemsParallel(items) {
  return Promise.all(items.map(item => processItem(item)));
}

Error Handling with try/catch

Async/await uses try/catch for error handling, which is more intuitive than .catch() chains.

Basic try/catch

async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch failed:', error);
    throw error; // Re-throw or handle
  }
}

Multiple Error Points

async function complexOperation() {
  let user;
  let posts;
  
  try {
    user = await fetchUser();
  } catch (error) {
    console.error('User fetch failed:', error);
    user = defaultUser;
  }
  
  try {
    posts = await fetchPosts(user.id);
  } catch (error) {
    console.error('Posts fetch failed:', error);
    posts = [];
  }
  
  return { user, posts };
}

Finally Block

async function loadData() {
  showLoading();
  
  try {
    const data = await fetchData();
    renderData(data);
  } catch (error) {
    showError(error);
  } finally {
    hideLoading(); // Always runs
  }
}

Error Handling Patterns

// Pattern 1: Throw on error
async function getData() {
  const response = await fetch('/api/data');
  if (!response.ok) throw new Error('Failed');
  return response.json();
}

// Pattern 2: Return null on error
async function getDataSafe() {
  try {
    const response = await fetch('/api/data');
    if (!response.ok) return null;
    return response.json();
  } catch {
    return null;
  }
}

// Pattern 3: Tuple pattern
async function getDataTuple() {
  try {
    const response = await fetch('/api/data');
    if (!response.ok) return [null, new Error('Failed')];
    const data = await response.json();
    return [data, null];
  } catch (error) {
    return [null, error];
  }
}

// Usage
const [data, error] = await getDataTuple();
if (error) handleError(error);

Practice Problems

0/3solved
Build Async / Await Component

Create a reusable React component implementing Async / Await. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Async / Await Testing

Write unit and integration tests for Async / Await using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Async / Await Performance

Optimize Async / Await for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What does an async function always return?

Question 1 options

2. What does the await keyword do?

Question 2 options

3. How do you handle errors in async/await?

Question 3 options

4. What is wrong with this code? ```javascript async function getData() { const users = await fetch('/api/users'); const posts = await fetch('/api/posts'); } ```

Question 4 options

Flashcards

Question

What is async/await?

Answer

Syntax for working with Promises. async declares a function that returns a Promise. await pauses until a Promise settles.

Question

What does an async function return?

Answer

Always returns a Promise. Return values are wrapped in Promise.resolve().

Question

How to run promises in parallel with async/await?

Answer

Use Promise.all(): const [a, b] = await Promise.all([promiseA, promiseB]);

Question

Can you use await at the top level?

Answer

Yes, in ES modules. Also in async IIFE: (async () => { await ... })()

Question

What is Async / Await?

Answer

Async / Await is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.Async functions always return Promises
  • 2.Await pauses execution until the Promise settles
  • 3.Use try/catch for error handling in async functions
  • 4.Use Promise.all() for parallel async operations
  • 5.Async/await makes Promise-based code more readable

Interview Tips

  • Explain the difference between sequential and parallel async operations
  • Be able to convert Promise chains to async/await syntax
  • Discuss error handling strategies with try/catch
  • Know when to use Promise.all() vs sequential awaits

Cheat Sheet

Async/Await Cheat Sheet

Basic Syntax

async function name() {
  const result = await promise;
  return result;
}

Error Handling

try {
  const data = await fetchData();
} catch (error) {
  console.error(error);
} finally {
  cleanup();
}

Parallel Operations

const [a, b] = await Promise.all([
  fetchA(),
  fetchB()
]);

Key Points

  • async functions always return Promises
  • await pauses until Promise settles
  • Use try/catch for errors
  • Use Promise.all() for parallel operations