JavaScript Async Patterns

Promises, async/await, and practical patterns for managing asynchronous code.

Asynchronous programming is core to JavaScript. Here are the patterns I use.

From Callbacks to Async/Await

// Callbacks
fetchUser(1, (err, user) => {
  if (err) return console.error(err);
  console.log(user);
});

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

// Async/Await
const user = await fetchUser(1);

Promise Combinators

Promise.all

const [users, posts] = await Promise.all([
  fetchUsers(),
  fetchPosts()
]);

Promise.allSettled

const results = await Promise.allSettled([
  fetchUsers(),
  fetchPosts() // might fail
]);

Promise.race

const result = await Promise.race([
  fetchFromCache(),
  fetchFromNetwork()
]);

Retry Pattern

async function retry(fn, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      if (i === attempts - 1) throw err;
      await new Promise(r => setTimeout(r, 1000 * (i + 1)));
    }
  }
}

Error Handling

async function safeAsync(fn) {
  try {
    return [await fn(), null];
  } catch (error) {
    return [null, error];
  }
}

const [data, error] = await safeAsync(() => fetchUser(1));