JavaScript
01 / 07

Async Programming (Promises & Async/Await)

JavaScript Async Programming

Asynchronous programming is essential in JavaScript for handling operations like API calls, file I/O, and timers without blocking the main thread.

Promises

// Creating a promise
const promise = new Promise((resolve, reject) => {
  const success = true;
  
  if (success) {
    resolve('Operation successful');
  } else {
    reject('Operation failed');
  }
});

// Consuming promises
promise
  .then(result => {
    console.log(result);  // 'Operation successful'
    return 'Next value';
  })
  .then(result => {
    console.log(result);  // 'Next value'
  })
  .catch(error => {
    console.error(error);
  })
  .finally(() => {
    console.log('Always runs');
  });

// Async operation
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: 'John' });
      } else {
        reject('Invalid ID');
      }
    }, 1000);
  });
}

fetchUser(1)
  .then(user => console.log(user))
  .catch(error => console.error(error));

// Promise.all - wait for all
const promise1 = fetch('/api/users');
const promise2 = fetch('/api/posts');
const promise3 = fetch('/api/comments');

Promise.all([promise1, promise2, promise3])
  .then(([users, posts, comments]) => {
    console.log('All data loaded');
  })
  .catch(error => {
    console.error('One promise failed:', error);
  });

// Promise.allSettled - wait for all, don't fail
Promise.allSettled([promise1, promise2, promise3])
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Promise ${index} succeeded:`, result.value);
      } else {
        console.log(`Promise ${index} failed:`, result.reason);
      }
    });
  });

// Promise.race - first to complete
Promise.race([promise1, promise2, promise3])
  .then(result => {
    console.log('First to finish:', result);
  });

// Promise.any - first to succeed
Promise.any([promise1, promise2, promise3])
  .then(result => {
    console.log('First success:', result);
  })
  .catch(error => {
    console.log('All failed:', error);
  });

Async/Await

// Basic async/await
async function getUser(id) {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  return user;
}

// Calling async function
getUser(1)
  .then(user => console.log(user))
  .catch(error => console.error(error));

// Or with async context
(async () => {
  try {
    const user = await getUser(1);
    console.log(user);
  } catch (error) {
    console.error(error);
  }
})();

// Error handling
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Fetch failed:', error);
    throw error;  // Re-throw or handle
  }
}

// Sequential vs Parallel
// Sequential (slower)
async function sequential() {
  const user = await fetchUser();      // Wait 1s
  const posts = await fetchPosts();    // Wait 1s
  const comments = await fetchComments();  // Wait 1s
  // Total: 3s
}

// Parallel (faster)
async function parallel() {
  const [user, posts, comments] = await Promise.all([
    fetchUser(),
    fetchPosts(),
    fetchComments()
  ]);
  // Total: 1s (all run simultaneously)
}

// Top-level await (in modules)
const data = await fetch('/api/data');
const json = await data.json();
export default json;

Callbacks vs Promises vs Async/Await

// Callback hell
getUser(1, (error, user) => {
  if (error) return console.error(error);
  
  getPosts(user.id, (error, posts) => {
    if (error) return console.error(error);
    
    getComments(posts[0].id, (error, comments) => {
      if (error) return console.error(error);
      
      console.log(comments);
    });
  });
});

// Promises - better
getUser(1)
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => console.log(comments))
  .catch(error => console.error(error));

// Async/await - best
async function loadData() {
  try {
    const user = await getUser(1);
    const posts = await getPosts(user.id);
    const comments = await getComments(posts[0].id);
    console.log(comments);
  } catch (error) {
    console.error(error);
  }
}

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free