Master asynchronous JavaScript patterns including callbacks, promises, async/await, event loop mechanics, and real-world async patterns.
Provides async/await, Promise patterns, and event loop knowledge for handling API calls, timeouts, and parallel operations. Triggers when writing asynchronous JavaScript code.
/plugin marketplace add pluginagentmarketplace/custom-plugin-javascript/plugin install javascript-developer-plugin@pluginagentmarketplace-javascriptThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/async-patterns.yamlassets/config.yamlreferences/ASYNC-AWAIT-GUIDE.mdreferences/GUIDE.mdscripts/helper.pyscripts/promise-utils.js1. Call Stack (sync code)
2. Microtasks (Promise.then, queueMicrotask)
3. Macrotasks (setTimeout, setInterval, I/O)
console.log('1'); // Sync
setTimeout(() => console.log('2'), 0); // Macro
Promise.resolve().then(() => console.log('3')); // Micro
console.log('4'); // Sync
// Output: 1, 4, 3, 2
// Create
const promise = new Promise((resolve, reject) => {
if (success) resolve(value);
else reject(new Error('Failed'));
});
// Chain
fetch('/api/data')
.then(res => res.json())
.then(data => process(data))
.catch(err => handleError(err))
.finally(() => cleanup());
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Fetch failed:', error);
throw error;
}
}
// All must succeed
const [a, b, c] = await Promise.all([p1, p2, p3]);
// All results (even failures)
const results = await Promise.allSettled([p1, p2, p3]);
results.forEach(r => {
if (r.status === 'fulfilled') console.log(r.value);
else console.log(r.reason);
});
// First to settle
const fastest = await Promise.race([p1, p2, p3]);
// First to succeed
const firstSuccess = await Promise.any([p1, p2, p3]);
// Sequential (slow)
const a = await fetch('/a');
const b = await fetch('/b');
// Parallel (fast)
const [a, b] = await Promise.all([
fetch('/a'),
fetch('/b')
]);
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, 2 ** i * 1000));
}
}
}
async function fetchWithTimeout(url, ms = 5000) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), ms);
try {
const res = await fetch(url, { signal: controller.signal });
return await res.json();
} finally {
clearTimeout(timeout);
}
}
function debounce(fn, delay) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
class RateLimiter {
constructor(limit, interval) {
this.tokens = limit;
setInterval(() => this.tokens = limit, interval);
}
async acquire() {
while (this.tokens <= 0) {
await new Promise(r => setTimeout(r, 100));
}
this.tokens--;
}
}
| Problem | Symptom | Fix |
|---|---|---|
| Unhandled rejection | Console warning | Add .catch() or try/catch |
| Sequential instead of parallel | Slow execution | Use Promise.all() |
Missing await | Promise instead of value | Add await |
| Race condition | Inconsistent results | Use proper sequencing |
// 1. Add timing
console.time('fetch');
await fetchData();
console.timeEnd('fetch');
// 2. Log promise state
promise.then(console.log).catch(console.error);
// 3. Check for missing await
const result = fetchData();
console.log(result); // Promise? Add await!
// 4. Trace async chain
async function debug() {
console.log('Step 1');
const a = await step1();
console.log('Step 2', a);
const b = await step2(a);
console.log('Done', b);
}
// Wrapper for tuple return
async function safeAsync(promise) {
try {
return [await promise, null];
} catch (error) {
return [null, error];
}
}
const [data, error] = await safeAsync(fetchData());
if (error) handleError(error);
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.