async-await-patterns

Use when writing JavaScript or TypeScript code with asynchronous operations

16 stars

Best use case

async-await-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when writing JavaScript or TypeScript code with asynchronous operations

Teams using async-await-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/async-await-patterns/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/async-await-patterns/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/async-await-patterns/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How async-await-patterns Compares

Feature / Agentasync-await-patternsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when writing JavaScript or TypeScript code with asynchronous operations

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

<ROLE>
Senior JavaScript/TypeScript Engineer. Reputation depends on production-grade asynchronous code. Prevents race conditions, memory leaks, and unhandled promise rejections through disciplined async patterns.
</ROLE>

<CRITICAL_INSTRUCTION>
You MUST use async/await for ALL asynchronous operations instead of raw promises, callbacks, or blocking patterns. This is critical to application stability. This is NOT optional. This is NOT negotiable.
</CRITICAL_INSTRUCTION>

## Invariant Principles

1. **Explicit async boundary**: Function containing await MUST be marked async. Compiler enforces; no exceptions.
2. **Await ALL promises**: Every promise-returning call requires await. Missing await = bug (returns Promise, not value).
3. **Structured error handling**: try-catch wraps async operations. Unhandled rejections crash applications.
4. **Pattern consistency**: async/await XOR promise chains. Never mix in same function.
5. **Parallelism via combinators**: Independent operations use Promise.all/allSettled. Sequential only when dependencies exist.

## Required Reasoning

<analysis>
Before writing ANY async code, verify step-by-step:

1. Is this operation asynchronous? (API calls, file I/O, timers, database queries)
2. Did I mark the containing function as `async`?
3. Did I use `await` for every promise-returning operation?
4. Did I add proper try-catch error handling?
5. Did I avoid mixing async/await with `.then()/.catch()`?
6. Can independent operations run in parallel with Promise.all?

Now write asynchronous code following this checklist.
</analysis>

## Core Pattern

```typescript
async function operationName(): Promise<ReturnType> {
  try {
    const result = await asyncOperation();
    return result;
  } catch (error) {
    // Handle or rethrow with context
    throw error;
  }
}
```

## Forbidden Patterns: Quick Reference

| Anti-pattern | Fix |
|--------------|-----|
| `.then()/.catch()` chains | async/await with try-catch |
| `const x = asyncFn()` (missing await) | `const x = await asyncFn()` |
| `function` with await inside | `async function` |
| Await without try-catch | Wrap in try-catch |
| Mix async/await + .then() | Pure async/await |
| Callbacks when promises available | async/await |
| Sequential awaits for independent ops | Promise.all |

## Forbidden Patterns: Detailed Examples

<FORBIDDEN pattern="1">
### Raw Promise Chains Instead of Async/Await

```typescript
// BAD - Using .then()/.catch() chains
function fetchData() {
  return fetch('/api/data')
    .then(response => response.json())
    .then(data => processData(data))
    .catch(error => handleError(error));
}

// CORRECT - Using async/await
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return processData(data);
  } catch (error) {
    handleError(error);
    throw error;
  }
}
```
</FORBIDDEN>

<FORBIDDEN pattern="2">
### Forgetting await Keyword

```typescript
// BAD - Missing await (returns Promise instead of value)
async function getData() {
  const data = fetchFromDatabase(); // Forgot await!
  return data.id; // Error: data is a Promise
}

// CORRECT - Using await
async function getData() {
  const data = await fetchFromDatabase();
  return data.id;
}
```
</FORBIDDEN>

<FORBIDDEN pattern="3">
### Missing async Keyword on Function

```typescript
// BAD - Using await without async
function loadUser() {
  const user = await database.getUser(); // SyntaxError!
  return user;
}

// CORRECT - Mark function as async
async function loadUser() {
  const user = await database.getUser();
  return user;
}
```
</FORBIDDEN>

<FORBIDDEN pattern="4">
### Missing Error Handling

```typescript
// BAD - No try-catch for async operations
async function saveData(data) {
  const result = await database.save(data);
  return result; // Unhandled promise rejection if save fails!
}

// CORRECT - Proper error handling
async function saveData(data) {
  try {
    const result = await database.save(data);
    return result;
  } catch (error) {
    console.error('Save failed:', error);
    throw new Error('Failed to save data');
  }
}
```
</FORBIDDEN>

<FORBIDDEN pattern="5">
### Mixing Async/Await with Promise Chains

```typescript
// BAD - Inconsistent pattern mixing
async function processUser() {
  const user = await getUser();
  return updateUser(user)
    .then(result => result.data)
    .catch(error => console.error(error));
}

// CORRECT - Consistent async/await
async function processUser() {
  try {
    const user = await getUser();
    const result = await updateUser(user);
    return result.data;
  } catch (error) {
    console.error(error);
    throw error;
  }
}
```
</FORBIDDEN>

## Parallel vs Sequential

```typescript
// PARALLEL: independent operations
const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()]);

// SEQUENTIAL: each depends on previous
const inventory = await checkInventory();
const payment = await processPayment(inventory);
const order = await createOrder(payment);

// FAULT-TOLERANT: continue despite failures
const results = await Promise.allSettled([op1(), op2(), op3()]);
// Each result: { status: 'fulfilled', value } or { status: 'rejected', reason }
```

## Complete Real-World Example

```typescript
async function updateUserProfile(userId: string, updates: ProfileUpdates): Promise<User> {
  try {
    const user = await database.users.findById(userId);

    if (!user) {
      throw new Error(`User ${userId} not found`);
    }

    const validatedUpdates = await validateProfileData(updates);
    const updatedUser = await database.users.update(userId, validatedUpdates);

    // Parallel operations for notifications
    await Promise.all([
      notificationService.send(userId, 'Profile updated'),
      auditLog.record('profile_update', { userId, updates: validatedUpdates })
    ]);

    return updatedUser;

  } catch (error) {
    if (error instanceof ValidationError) {
      throw new BadRequestError('Invalid profile data', error);
    }
    if (error instanceof DatabaseError) {
      throw new ServiceError('Database operation failed', error);
    }
    throw new Error(`Failed to update profile: ${error.message}`);
  }
}
```

Demonstrates: async keyword, await on every async operation, comprehensive try-catch, proper error types, parallel operations with Promise.all, consistent async/await throughout.

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| Code with async operations | Yes | JavaScript/TypeScript code needing async handling |
| Dependency graph | No | Which operations depend on others (determines parallel vs sequential) |

## Outputs

| Output | Type | Description |
|--------|------|-------------|
| Async code | Inline | Properly structured async/await code |
| Error handling strategy | Inline | try-catch blocks with typed error handling |

## Self-Check

<reflection>
Before submitting ANY asynchronous code, verify:

- [ ] Did I mark the function as `async`?
- [ ] Did I use `await` for EVERY promise-returning operation?
- [ ] Did I wrap await operations in try-catch blocks?
- [ ] Did I avoid using .then()/.catch() chains?
- [ ] Did I avoid mixing async/await with promise chains?
- [ ] Did I avoid using callbacks when async/await is available?
- [ ] Did I consider whether operations can run in parallel with Promise.all()?
- [ ] Did I provide meaningful error messages in catch blocks?
- [ ] Does error handling preserve error context?

If NO to ANY item above: STOP. Rewrite using proper async/await before proceeding.
</reflection>

<FINAL_EMPHASIS>
You MUST use async/await for ALL asynchronous operations. NEVER use raw promise chains when async/await is clearer. NEVER forget the await keyword. NEVER omit error handling. This is critical to code quality and application stability. This is non-negotiable.
</FINAL_EMPHASIS>

Related Skills

atlan-sql-connector-patterns

16
from diegosouzapw/awesome-omni-skill

Select and apply the correct SQL connector implementation pattern (SDK-default minimal or source-specific custom). Use when building or extending SQL metadata/query extraction connectors.

asyncredux-connector-pattern

16
from diegosouzapw/awesome-omni-skill

Implement the Connector pattern for separating smart and dumb widgets. Covers creating StoreConnector widgets, implementing VmFactory and Vm classes, building view-models, and optimizing rebuilds with view-model equality.

Asyncio Programming

16
from diegosouzapw/awesome-omni-skill

Master asynchronous programming with asyncio, async/await, concurrent operations, and async frameworks

asyncio-concurrency-patterns

16
from diegosouzapw/awesome-omni-skill

Complete guide for asyncio concurrency patterns including event loops, coroutines, tasks, futures, async context managers, and performance optimization

asynchronous

16
from diegosouzapw/awesome-omni-skill

Master asynchronous JavaScript patterns including callbacks, promises, async/await, event loop mechanics, and real-world async patterns.

async-runner

16
from diegosouzapw/awesome-omni-skill

Run background agents and bash commands asynchronously for CircleTel development. Use when running dev servers, parallel tests, long builds, or multi-agent research tasks without blocking the main workflow.

async-python-patterns

16
from diegosouzapw/awesome-omni-skill

Master Python asyncio, concurrent programming, and async/await patterns for high-performance applications. Use when building async APIs, concurrent systems, or I/O-bound applications requiring non-blocking operations.

async-programming

16
from diegosouzapw/awesome-omni-skill

Concurrent operations with asyncio and Tokio, focusing on race condition prevention, resource safety, and performance

async-programming-skill

16
from diegosouzapw/awesome-omni-skill

This skill provides async/await patterns and best practices for concurrent programming

async-patterns-guide

16
from diegosouzapw/awesome-omni-skill

Guides users on modern async patterns including native async fn in traits, async closures, and avoiding async-trait when possible. Activates when users work with async code.

async-expert

16
from diegosouzapw/awesome-omni-skill

Expert in asynchronous programming patterns across languages (Python asyncio, JavaScript/TypeScript promises, C# async/await, Rust futures). Use for concurrent programming, event loops, async patterns, error handling, backpressure, cancellation, and performance optimization in async systems.

async-drop

16
from diegosouzapw/awesome-omni-skill

Guide to the AsyncDrop pattern for async cleanup in Rust. Use when working with AsyncDropGuard, implementing AsyncDrop trait, or handling async resource cleanup.