Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Async / Await

async/await with Fetch

The async/await syntax (ES2017) makes asynchronous code look and behave like synchronous code. An async function always returns a Promise. Inside it, await pauses execution until the awaited Promise resolves — without blocking the main thread.

Basic async/await with Fetch
// async function — always returns a Promise
async function getUser(id) {
  // try-catch replaces .catch() for error handling
  try {
    const response = await fetch(`/api/users/${id}`);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const user = await response.json(); // await the body parsing too
    return user;

  } catch (error) {
    console.error('getUser failed:', error.message);
    throw error; // re-throw so callers can handle it
  } finally {
    // finally always runs — good for cleanup
    console.log('getUser request complete');
  }
}

// Call the async function
getUser(1)
  .then(user => console.log('User:', user.name))
  .catch(err => console.error('Caught:', err.message));
Sequential vs Parallel Requests
// ---- SEQUENTIAL — each request waits for the previous ----
// Total time = sum of all request times (slow!)
async function loadSequential() {
  const user    = await fetch('/api/users/1').then(r => r.json());
  const posts   = await fetch('/api/posts?userId=1').then(r => r.json());
  const profile = await fetch('/api/profile/1').then(r => r.json());
  // Runs in series: user → posts → profile
  return { user, posts, profile };
}

// ---- PARALLEL with Promise.all — all requests fire simultaneously ----
// Total time = longest single request (fast!)
async function loadParallel() {
  const [user, posts, profile] = await Promise.all([
    fetch('/api/users/1').then(r => r.json()),
    fetch('/api/posts?userId=1').then(r => r.json()),
    fetch('/api/profile/1').then(r => r.json())
  ]);
  // All three requests run concurrently
  return { user, posts, profile };
}

// ---- Promise.allSettled — get results even if some fail ----
async function loadWithFallback() {
  const results = await Promise.allSettled([
    fetch('/api/users/1').then(r => r.json()),
    fetch('/api/posts?userId=1').then(r => r.json()),
    fetch('/api/missing-endpoint').then(r => r.json()) // this will fail
  ]);

  results.forEach((result, i) => {
    if (result.status === 'fulfilled') {
      console.log(`Request ${i} succeeded:`, result.value);
    } else {
      console.warn(`Request ${i} failed:`, result.reason.message);
    }
  });
}
Async IIFE and Top-Level Await
// Async IIFE — run async code at the top level (pre-ES2022)
(async () => {
  try {
    const res = await fetch('/api/config');
    const config = await res.json();
    console.log('App config loaded:', config);
    initApp(config);
  } catch (err) {
    console.error('Failed to load config:', err);
  }
})();

// Top-level await (ES2022, requires type="module")
// <script type="module">
//   const res = await fetch('/api/config');
//   const config = await res.json();
//   initApp(config);
// </script>

// Error propagation through async call chains
async function step1() {
  const data = await fetch('/api/step1').then(r => r.json());
  return data.value;
}

async function step2(value) {
  const data = await fetch(`/api/step2?v=${value}`).then(r => r.json());
  return data.result;
}

async function runPipeline() {
  try {
    const v1 = await step1();
    const v2 = await step2(v1);
    console.log('Pipeline result:', v2);
  } catch (err) {
    // Catches errors from step1 OR step2
    console.error('Pipeline failed:', err.message);
  }
}
Real-World Async/Await Patterns
// Pattern 1: Loading state management
async function loadAndRender(url, containerId) {
  const container = document.getElementById(containerId);
  container.innerHTML = '<div class="spinner">Loading...</div>';

  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const data = await res.json();
    container.innerHTML = renderData(data);
  } catch (err) {
    container.innerHTML = `<p class="error">${err.message}</p>`;
  }
}

// Pattern 2: Polling — check for updates every N seconds
async function pollForStatus(jobId, intervalMs = 2000) {
  while (true) {
    const res = await fetch(`/api/jobs/${jobId}`);
    const job = await res.json();

    if (job.status === 'completed') {
      console.log('Job done:', job.result);
      break;
    } else if (job.status === 'failed') {
      throw new Error('Job failed: ' + job.error);
    }

    // Wait before next poll
    await new Promise(resolve => setTimeout(resolve, intervalMs));
  }
}

// Pattern 3: Race — use whichever request finishes first
async function fetchWithFallback(primaryUrl, fallbackUrl) {
  try {
    return await Promise.race([
      fetch(primaryUrl).then(r => r.json()),
      new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 3000))
    ]);
  } catch {
    console.warn('Primary failed, using fallback');
    return fetch(fallbackUrl).then(r => r.json());
  }
}

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.