Claude-skill-registry async-await-patterns
Use when writing JavaScript or TypeScript code with asynchronous operations
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/async-await-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-async-await-patterns && rm -rf "$T"
skills/data/async-await-patterns/SKILL.md<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
- Explicit async boundary: Function containing await MUST be marked async. Compiler enforces; no exceptions.
- Await ALL promises: Every promise-returning call requires await. Missing await = bug (returns Promise, not value).
- Structured error handling: try-catch wraps async operations. Unhandled rejections crash applications.
- Pattern consistency: async/await XOR promise chains. Never mix in same function.
- 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:- Is this operation asynchronous? (API calls, file I/O, timers, database queries)
- Did I mark the containing function as
?async - Did I use
for every promise-returning operation?await - Did I add proper try-catch error handling?
- Did I avoid mixing async/await with
?.then()/.catch() - Can independent operations run in parallel with Promise.all?
Now write asynchronous code following this checklist. </analysis>
Core Pattern
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 |
|---|---|
chains | async/await with try-catch |
(missing await) | |
with await inside | |
| 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</FORBIDDEN> <FORBIDDEN pattern="2"> ### Forgetting await Keyword// 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="3"> ### Missing async Keyword on Function// 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="4"> ### Missing Error Handling// 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="5"> ### Mixing Async/Await with Promise Chains// 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>// 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; } }
Parallel vs Sequential
// 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
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
for EVERY promise-returning operation?await - 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>