Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /Javascript
  4. /Async Await
Your Progress0%
0 of 61 completed

JavaScript Topics

Getting Started

  • What is JavaScript?
  • JavaScript vs Other Languages
  • Setting Up Your JavaScript Environment
  • Developer Console and Debugging Basics

JavaScript Fundamentals

  • Variables (var, let, const)
  • Data Types and Type Checking
  • Comments and Code Organization
  • String Methods and Template Literals
  • Type Conversion and Coercion
  • Operators (Arithmetic, Comparison, Logical)

Control Flow

  • If/Else Statements
  • Switch Statements
  • Ternary Operator
  • Truthy and Falsy Values
  • Logical Operators and Short-Circuiting

Loops and Iteration

  • For Loops
  • While and Do-While Loops
  • For...of and For...in Loops
  • Break and Continue Statements

Functions

  • Function Declarations and Expressions
  • Arrow Functions
  • Function Parameters and Arguments
  • Return Statements and Values
  • Scope and Closures
  • Higher-Order Functions and Callbacks

Arrays

  • Array Basics and Creation
  • Array Methods: Adding and Removing Elements
  • Array Iteration Methods (forEach, map, filter)
  • Array Methods: find, some, every, reduce
  • Sorting, Reversing, and Array Transformation

Objects

  • Object Basics and Properties
  • Object Methods and 'this' Keyword
  • Object Destructuring
  • Object.keys, values, entries
  • Spread Operator and Object Cloning

DOM Manipulation

  • Introduction to the DOM
  • Selecting Elements (querySelector, getElementById)
  • Modifying Elements (textContent, innerHTML, style)
  • Creating and Removing Elements
  • Event Listeners and Event Handling
  • Event Object and Event Delegation

Asynchronous JavaScript

  • Understanding Asynchronous Code
  • setTimeout and setInterval
  • Callbacks and Callback Hell
  • Promises and Promise Chaining
  • Async/Await

Error Handling

  • Try, Catch, Finally
  • Throwing Custom Errors

Modern JavaScript Features

  • ES6+ Overview
  • Modules (import/export)
  • Optional Chaining and Nullish Coalescing
  • Rest and Spread Operators

Working with Data

  • JSON (Parse and Stringify)
  • Fetch API and HTTP Requests
  • Working with Local Storage

Advanced Concepts

  • Classes and Object-Oriented Programming
  • Array and Object Advanced Patterns
  • Regular Expressions Basics

Best Practices & Real-World Application

  • JavaScript Best Practices
  • Debugging Techniques and Tools
  • Building a Complete Interactive Project

Async/Await

Modern syntax for beautiful asynchronous code

Async/await is syntactic sugar built on top of Promises, introduced in ES2017 (ES8). It allows you to write asynchronous code that looks and behaves like synchronous code, making it incredibly readable and maintainable. With async/await, you can avoid .then() chains and write async operations as if they were blocking, while still being non-blocking under the hood. It's the most elegant way to handle async operations in modern JavaScript. Let's master async/await!

The async Keyword

The async keyword before a function makes it return a Promise automatically.

JAVASCRIPT
// Regular function
function regularFunction() {
  return 'Hello';
}

console.log(regularFunction());  // "Hello"

// Async function
async function asyncFunction() {
  return 'Hello';
}

console.log(asyncFunction());  // Promise { 'Hello' }

// The return value is automatically wrapped in a Promise!

// Consuming async function
asyncFunction().then(result => {
  console.log(result);  // "Hello"
});

// Even if you explicitly return a Promise
async function explicitPromise() {
  return Promise.resolve('Hi');
}

explicitPromise().then(result => {
  console.log(result);  // "Hi" (not nested Promise)
});

Async Functions Always Return Promises

JAVASCRIPT
// Different ways to declare async functions

// Function declaration
async function fetchData() {
  return 'data';
}

// Function expression
const fetchData2 = async function() {
  return 'data';
};

// Arrow function
const fetchData3 = async () => {
  return 'data';
};

// Async method in object
const obj = {
  async getData() {
    return 'data';
  }
};

// Async method in class
class DataFetcher {
  async fetchData() {
    return 'data';
  }
}

// All of these return Promises!
fetchData().then(d => console.log(d));
fetchData2().then(d => console.log(d));
fetchData3().then(d => console.log(d));
obj.getData().then(d => console.log(d));
new DataFetcher().fetchData().then(d => console.log(d));

The await Keyword

The await keyword pauses async function execution until a Promise resolves, then returns the resolved value.

JAVASCRIPT
// Without await (Promise-based)
function getData() {
  return fetchData().then(data => {
    return processData(data);
  }).then(result => {
    return saveData(result);
  });
}

// With await (cleaner!)
async function getData() {
  let data = await fetchData();      // Wait for promise
  let result = await processData(data);  // Wait for promise
  await saveData(result);            // Wait for promise
  return 'Done';
}

// await makes async code look synchronous!

// Example with real delay
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Start');
  await delay(2000);  // Wait 2 seconds
  console.log('After 2 seconds');
  await delay(1000);  // Wait 1 second
  console.log('After 3 seconds total');
}

demo();
// Output:
// Start
// (2 seconds pause...)
// After 2 seconds
// (1 second pause...)
// After 3 seconds total

await Unwraps Promises

JAVASCRIPT
async function example() {
  // Promise.resolve returns a Promise
  let promise = Promise.resolve('Hello');
  
  // await unwraps the Promise, giving you the value
  let value = await promise;
  
  console.log(value);  // "Hello" (not a Promise!)
  
  // You can use the value directly
  console.log(value.toUpperCase());  // "HELLO"
}

// Without await, you'd need .then()
function exampleWithoutAwait() {
  let promise = Promise.resolve('Hello');
  
  promise.then(value => {
    console.log(value);
    console.log(value.toUpperCase());
  });
}

// await is much cleaner!

Important: await can only be used inside async functions (or at the top level of ES modules). Using it elsewhere causes a syntax error.

Promise Chains vs Async/Await

Async/await is more readable

Promise Chains

// Promise chains (.then)
function getUserData(userId) {
  return getUser(userId)
    .then(user => {
      console.log('User:', user.name);
      return getPosts(user.id);
    })
    .then(posts => {
      console.log('Posts:', posts.length);
      return getComments(posts[0].id);
    })
    .then(comments => {
      console.log('Comments:', comments.length);
      return comments;
    })
    .catch(error => {
      console.log('Error:', error.message);
      throw error;
    });
}

// Still readable, but...
// Multiple .then() calls
// Need to return promises
// Nesting for multiple operations
Output:
Not run yet...

Async/Await

// Async/await (cleaner!)
async function getUserData(userId) {
  try {
    let user = await getUser(userId);
    console.log('User:', user.name);
    
    let posts = await getPosts(user.id);
    console.log('Posts:', posts.length);
    
    let comments = await getComments(posts[0].id);
    console.log('Comments:', comments.length);
    
    return comments;
  } catch (error) {
    console.log('Error:', error.message);
    throw error;
  }
}

// Looks synchronous!
// Easy to read top-to-bottom
// Natural error handling
Output:
Not run yet...

Error Handling with Try-Catch

Basic Try-Catch

JAVASCRIPT
async function fetchUserData(userId) {
  try {
    let user = await getUser(userId);
    console.log('User:', user.name);
    return user;
  } catch (error) {
    console.log('Error fetching user:', error.message);
    // Handle error, return default, or re-throw
    return null;
  }
}

// Multiple operations
async function processData() {
  try {
    let data = await fetchData();
    let processed = await processStep1(data);
    let final = await processStep2(processed);
    return final;
  } catch (error) {
    console.log('Processing failed:', error.message);
    throw error;  // Re-throw for caller to handle
  }
}

// Usage
processData()
  .then(result => console.log('Success:', result))
  .catch(error => console.log('Failed:', error));

Specific Error Handling

JAVASCRIPT
async function loadUserProfile(userId) {
  try {
    let user = await getUser(userId);
    
    try {
      let avatar = await loadAvatar(user.avatarUrl);
      return { user, avatar };
    } catch (avatarError) {
      // Avatar failed, but continue with default
      console.log('Avatar failed, using default');
      return { user, avatar: null };
    }
  } catch (userError) {
    // User fetch failed - critical error
    console.log('Failed to load user:', userError.message);
    throw userError;
  }
}

// Handling specific error types
async function fetchData(url) {
  try {
    let response = await fetch(url);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    
    let data = await response.json();
    return data;
  } catch (error) {
    if (error.name === 'TypeError') {
      console.log('Network error:', error.message);
    } else if (error.message.includes('HTTP')) {
      console.log('Server error:', error.message);
    } else {
      console.log('Unknown error:', error.message);
    }
    throw error;
  }
}

Finally Block

JAVASCRIPT
async function loadData() {
  showLoadingSpinner();
  
  try {
    let data = await fetchData();
    let processed = await processData(data);
    displayData(processed);
  } catch (error) {
    showError(error.message);
  } finally {
    // Always runs, regardless of success or failure
    hideLoadingSpinner();
    console.log('Loading complete');
  }
}

// Finally is perfect for cleanup
async function updateDatabase() {
  let connection = await connectToDatabase();
  
  try {
    await connection.beginTransaction();
    await connection.query('UPDATE ...');
    await connection.commit();
  } catch (error) {
    await connection.rollback();
    throw error;
  } finally {
    // Always close connection
    await connection.close();
  }
}

Parallel Execution

Sequential vs Parallel

JAVASCRIPT
// Sequential (one after another)
async function sequential() {
  console.time('Sequential');
  
  let user = await getUser(1);      // Wait 1 second
  let posts = await getPosts(1);    // Wait 1 second
  let comments = await getComments(1); // Wait 1 second
  
  console.timeEnd('Sequential');  // ~3 seconds
  return { user, posts, comments };
}

// Parallel (all at once!)
async function parallel() {
  console.time('Parallel');
  
  // Start all promises simultaneously
  let [user, posts, comments] = await Promise.all([
    getUser(1),
    getPosts(1),
    getComments(1)
  ]);
  
  console.timeEnd('Parallel');  // ~1 second (fastest)
  return { user, posts, comments };
}

// When operations don't depend on each other, run them in parallel!

Starting Promises Before Awaiting

JAVASCRIPT
// Inefficient: Sequential
async function inefficient() {
  let data1 = await fetchData1();  // Wait
  let data2 = await fetchData2();  // Wait
  let data3 = await fetchData3();  // Wait
  return [data1, data2, data3];
}

// Efficient: Start all, then await all
async function efficient() {
  // Start all promises (don't await yet)
  let promise1 = fetchData1();
  let promise2 = fetchData2();
  let promise3 = fetchData3();
  
  // Now await all (they're already running!)
  let data1 = await promise1;
  let data2 = await promise2;
  let data3 = await promise3;
  
  return [data1, data2, data3];
}

// Or use Promise.all
async function withPromiseAll() {
  let results = await Promise.all([
    fetchData1(),
    fetchData2(),
    fetchData3()
  ]);
  return results;
}

Common Async/Await Patterns

Pattern 1: Conditional Async Operations

JAVASCRIPT
async function loadUserData(userId, options = {}) {
  let user = await getUser(userId);
  
  let data = { user };
  
  // Conditionally load additional data
  if (options.includePosts) {
    data.posts = await getPosts(userId);
  }
  
  if (options.includeComments) {
    data.comments = await getComments(userId);
  }
  
  if (options.includeFriends) {
    data.friends = await getFriends(userId);
  }
  
  return data;
}

// Usage
let basicData = await loadUserData(1);
let fullData = await loadUserData(1, {
  includePosts: true,
  includeComments: true,
  includeFriends: true
});

Pattern 2: Retry Logic

JAVASCRIPT
async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      let response = await fetch(url);
      return await response.json();
    } catch (error) {
      console.log(`Attempt ${i + 1} failed`);
      
      if (i === maxRetries - 1) {
        throw error;  // Last attempt failed
      }
      
      // Wait before retrying (exponential backoff)
      await delay(1000 * Math.pow(2, i));
    }
  }
}

// Usage
try {
  let data = await fetchWithRetry('/api/data');
  console.log('Data loaded:', data);
} catch (error) {
  console.log('All retries failed:', error);
}

Pattern 3: Sequential Processing with Accumulation

JAVASCRIPT
async function processUsers(userIds) {
  let results = [];
  
  for (let userId of userIds) {
    try {
      let user = await getUser(userId);
      let processed = await processUser(user);
      results.push(processed);
    } catch (error) {
      console.log(`Failed to process user ${userId}`);
      results.push(null);
    }
  }
  
  return results;
}

// Process in batches
async function processBatch(items, batchSize = 5) {
  let results = [];
  
  for (let i = 0; i < items.length; i += batchSize) {
    let batch = items.slice(i, i + batchSize);
    
    // Process batch in parallel
    let batchResults = await Promise.all(
      batch.map(item => processItem(item))
    );
    
    results.push(...batchResults);
  }
  
  return results;
}

Pattern 4: Race with Timeout

JAVASCRIPT
async function fetchWithTimeout(url, timeoutMs = 5000) {
  let timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error('Request timeout'));
    }, timeoutMs);
  });
  
  try {
    let response = await Promise.race([
      fetch(url),
      timeoutPromise
    ]);
    return await response.json();
  } catch (error) {
    if (error.message === 'Request timeout') {
      console.log('Request took too long');
    }
    throw error;
  }
}

// Usage
try {
  let data = await fetchWithTimeout('/api/data', 3000);
  console.log('Data:', data);
} catch (error) {
  console.log('Failed:', error.message);
}

Practical Examples

Example 1: User Dashboard

JAVASCRIPT
async function loadUserDashboard(userId) {
  try {
    // Show loading state
    showLoading();
    
    // Load user data first (needed for other requests)
    let user = await getUser(userId);
    displayUserHeader(user);
    
    // Load other data in parallel (doesn't depend on each other)
    let [posts, stats, friends, notifications] = await Promise.all([
      getUserPosts(userId),
      getUserStats(userId),
      getUserFriends(userId),
      getUserNotifications(userId)
    ]);
    
    // Display everything
    displayPosts(posts);
    displayStats(stats);
    displayFriends(friends);
    displayNotifications(notifications);
    
    console.log('Dashboard loaded successfully');
  } catch (error) {
    console.error('Failed to load dashboard:', error);
    showError('Could not load dashboard. Please try again.');
  } finally {
    hideLoading();
  }
}

// Usage
loadUserDashboard(currentUserId);

Example 2: Form Submission with Validation

JAVASCRIPT
async function submitRegistrationForm(formData) {
  try {
    // Client-side validation
    validateFormData(formData);
    
    // Check if email exists (async validation)
    let emailExists = await checkEmailExists(formData.email);
    if (emailExists) {
      throw new Error('Email already registered');
    }
    
    // Check if username is available
    let usernameAvailable = await checkUsernameAvailable(formData.username);
    if (!usernameAvailable) {
      throw new Error('Username already taken');
    }
    
    // Submit the form
    let response = await fetch('/api/register', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(formData)
    });
    
    if (!response.ok) {
      throw new Error('Registration failed');
    }
    
    let result = await response.json();
    
    // Success
    showSuccess('Registration successful!');
    redirectToLogin();
    
    return result;
  } catch (error) {
    showError(error.message);
    throw error;
  }
}

// Usage
document.getElementById('registerForm').addEventListener('submit', async (e) => {
  e.preventDefault();
  
  let formData = {
    username: e.target.username.value,
    email: e.target.email.value,
    password: e.target.password.value
  };
  
  try {
    await submitRegistrationForm(formData);
  } catch (error) {
    console.log('Registration failed');
  }
});

Async/Await Mastery

Modern asynchronous JavaScript

Output:
Click "Run" to execute your code...
💡 Tip: Use console.log() to see your output in the console above.

Key Takeaways

  • async keyword makes function return a Promise
  • await pauses execution until Promise resolves
  • await can only be used inside async functions
  • Async/await makes async code look synchronous
  • Use try-catch for error handling (natural and readable)
  • Use finally for cleanup operations
  • Sequential: await one at a time (slower)
  • Parallel: use Promise.all for independent operations (faster)
  • Async functions are built on Promises (syntactic sugar)
  • Modern standard for async JavaScript—use it!

What's Next?

Congratulations! You've completed the Asynchronous JavaScript section and now understand the full evolution of async patterns—from callbacks to Promises to async/await. You've learned the most elegant way to write async code in modern JavaScript!

You've now completed 47 out of 62 JavaScript tutorial pages (76% complete)! You've mastered 10 major sections including async programming. You're well on your way to JavaScript mastery!

💪 Practice Challenge:

Before moving on, try creating:

  1. Convert Promise-based code to async/await
  2. Create an async function with proper try-catch error handling
  3. Load multiple resources in parallel using Promise.all with await
  4. Implement retry logic with async/await
  5. Build a user dashboard that loads data with async/await

Test Your Understanding

Question 1 / 4

What does the 'async' keyword do?

Score: 0 / 0

Mastering modern async JavaScript with async/await! 🚀

Previous
Promises and Promise Chaining
Next
Try, Catch, Finally

Continue Learning JavaScript

Join 2,000+ developers mastering JavaScript. New lessons weekly - 100% FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

JavaScript Tutorials

0 of 61 completed

Your Progress0%

Topics

Getting Started

  • What is JavaScript?
  • JavaScript vs Other Languages
  • Setting Up Your JavaScript Environment
  • Developer Console and Debugging Basics

JavaScript Fundamentals

  • Variables (var, let, const)
  • Data Types and Type Checking
  • Comments and Code Organization
  • String Methods and Template Literals
  • Type Conversion and Coercion
  • Operators (Arithmetic, Comparison, Logical)

Control Flow

  • If/Else Statements
  • Switch Statements
  • Ternary Operator
  • Truthy and Falsy Values
  • Logical Operators and Short-Circuiting

Loops and Iteration

  • For Loops
  • While and Do-While Loops
  • For...of and For...in Loops
  • Break and Continue Statements

Functions

  • Function Declarations and Expressions
  • Arrow Functions
  • Function Parameters and Arguments
  • Return Statements and Values
  • Scope and Closures
  • Higher-Order Functions and Callbacks

Arrays

  • Array Basics and Creation
  • Array Methods: Adding and Removing Elements
  • Array Iteration Methods (forEach, map, filter)
  • Array Methods: find, some, every, reduce
  • Sorting, Reversing, and Array Transformation

Objects

  • Object Basics and Properties
  • Object Methods and 'this' Keyword
  • Object Destructuring
  • Object.keys, values, entries
  • Spread Operator and Object Cloning

DOM Manipulation

  • Introduction to the DOM
  • Selecting Elements (querySelector, getElementById)
  • Modifying Elements (textContent, innerHTML, style)
  • Creating and Removing Elements
  • Event Listeners and Event Handling
  • Event Object and Event Delegation

Asynchronous JavaScript

  • Understanding Asynchronous Code
  • setTimeout and setInterval
  • Callbacks and Callback Hell
  • Promises and Promise Chaining
  • Async/Await

Error Handling

  • Try, Catch, Finally
  • Throwing Custom Errors

Modern JavaScript Features

  • ES6+ Overview
  • Modules (import/export)
  • Optional Chaining and Nullish Coalescing
  • Rest and Spread Operators

Working with Data

  • JSON (Parse and Stringify)
  • Fetch API and HTTP Requests
  • Working with Local Storage

Advanced Concepts

  • Classes and Object-Oriented Programming
  • Array and Object Advanced Patterns
  • Regular Expressions Basics

Best Practices & Real-World Application

  • JavaScript Best Practices
  • Debugging Techniques and Tools
  • Building a Complete Interactive Project
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo