Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计通过

async-over-callbacks异步回调

Agent Skill

async-over-callbacks 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

192

周安装

8

GitHub Stars

2

下载量

64
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:async-over-callbacks(异步回调)
来源仓库:https://github.com/marius-townhouse/effective-typescript-skills
仓库路径:skills/async-over-callbacks
安装命令:
npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill async-over-callbacks
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill async-over-callbacks

简介

async-over-callbacks 提供使用 async/await 替代回调函数的编程模式,适用于编写更清晰、类型安全的异步代码。

  • 适合处理 I/O 操作、并发系统构建、超时管理和取消机制等异步任务场景。
  • 核心能力包括避免嵌套回调、自然类型流传递和增强的错误处理支持。
  • 安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Use async Functions Instead of Callbacks

Overview

Prefer async/await over callbacks for cleaner code and better type flow.

Callbacks create nested, hard-to-follow code. Promises and async/await flatten the structure, make types flow naturally, and enable better error handling.

When to Use This Skill

  • Writing any asynchronous code
  • Tempted to use callback-style APIs
  • Chaining multiple async operations
  • Need to compose concurrent operations
  • Working with APIs that return Promises

The Iron Rule

ALWAYS prefer async/await over callbacks for new code.

Remember:

  • async/await is syntactic sugar over Promises
  • Types flow through Promises automatically
  • Error handling is cleaner with try/catch
  • Concurrent operations compose easily

Detection: The Callback Pyramid

If you see nested callbacks (the "pyramid of doom"), refactor to async/await:

// ❌ Callback hell - hard to read, types don't flow well
fetchURL(url1, function(response1) {
fetchURL(url2, function(response2) {
fetchURL(url3, function(response3) {
// ... deeply nested
console.log(1);
});
console.log(2);
});
console.log(3);
});
console.log(4);
// Logs: 4, 3, 2, 1 (confusing order!)

The async/await Solution

// ✅ Clean, flat, readable
async function fetchPages() {
const response1 = await fetch(url1);
const response2 = await fetch(url2);
const response3 = await fetch(url3);
// Execution order matches code order
}

Why Types Flow Better

Callbacks Require Manual Type Annotations

// ❌ Callbacks - you must annotate types
function fetchUser(
  id: string,
  callback: (user: User | null, error?: Error) => void
) {
  // ...
}

fetchUser('123', (user, error) => {
  if (error) { /* handle */ }
  if (user) { /* use user */ }
});

Promises Carry Types Automatically

// ✅ Promises - types flow through
async function fetchUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();  // TypeScript knows this returns Promise<User>
}

const user = await fetchUser('123');
//    ^? const user: User

Composing Async Operations

Sequential Operations

async function getFullUserData(id: string) {
  const user = await fetchUser(id);
  const posts = await fetchPosts(user.id);
  const comments = await fetchComments(posts);
  return { user, posts, comments };
}
// Return type is automatically inferred

Concurrent Operations with Promise.all

async function fetchAllPages() {
  // Run all fetches concurrently, wait for all to complete
  const [page1, page2, page3] = await Promise.all([
    fetch(url1),
    fetch(url2),
    fetch(url3),
  ]);
  // Types are inferred: [Response, Response, Response]
}

Race Conditions with Promise.race

async function fetchWithTimeout(url: string, ms: number) {
  return Promise.race([
    fetch(url),
    new Promise<never>((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), ms)
    ),
  ]);
}

Error Handling

Callbacks: Error-First Convention (Manual)

// ❌ Manual error handling, easy to forget
fetchData(url, (error, data) => {
  if (error) {
    console.error(error);
    return;
  }
  // use data
});

async/await: Natural try/catch

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

Common Patterns

Always Return Promises from async Functions

// ❌ Inconsistent return type
function getQuote(ticker: string) {
  if (cache[ticker]) {
    return cache[ticker];  // Returns number
  }
  return fetch(`/quote?t=${ticker}`)
    .then(r => r.json());  // Returns Promise<number>
}
// Type: number | Promise<number> - confusing!

// ✅ Consistent Promise return
async function getQuote(ticker: string): Promise<number> {
  if (cache[ticker]) {
    return cache[ticker];  // Automatically wrapped in Promise
  }
  const response = await fetch(`/quote?t=${ticker}`);
  return response.json();
}

Annotate Return Types for Clarity

// ✅ Explicit return type catches mistakes
async function fetchUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  // TypeScript ensures we return a User
  return response.json();
}

Use Promise.allSettled for Partial Failures

async function fetchAllUsers(ids: string[]) {
  const results = await Promise.allSettled(
    ids.map(id => fetchUser(id))
  );

  // Handle both successes and failures
  const users: User[] = [];
  for (const result of results) {
    if (result.status === 'fulfilled') {
      users.push(result.value);
    } else {
      console.error('Failed:', result.reason);
    }
  }
  return users;
}

Converting Callbacks to Promises

Using util.promisify (Node.js)

import { promisify } from 'util';
import { readFile } from 'fs';

const readFileAsync = promisify(readFile);

async function loadConfig() {
  const data = await readFileAsync('config.json', 'utf-8');
  return JSON.parse(data);
}

Manual Promisification

function fetchURLAsync(url: string): Promise<string> {
  return new Promise((resolve, reject) => {
    fetchURL(url, (response, error) => {
      if (error) {
        reject(error);
      } else {
        resolve(response);
      }
    });
  });
}

Immediate Execution in async Functions

// async functions return a Promise, even with immediate values
async function getValue(): Promise<number> {
  return 42;  // Wrapped in Promise.resolve(42)
}

// To unwrap, you must await
const value = await getValue();
//    ^? const value: number

Pressure Resistance Protocol

1. "Callbacks Are Faster"

Pressure: "Promises have overhead, callbacks are more performant"

Response: The overhead is negligible. Code clarity and type safety matter more.

Action: Use async/await. Profile if you suspect performance issues.

2. "The API Only Supports Callbacks"

Pressure: "This library uses callbacks, we have to use them too"

Response: Wrap callback APIs in Promises.

Action: Use promisify or create a Promise wrapper.

3. "We're Already Using Callbacks Everywhere"

Pressure: "Consistency with existing code"

Response: Gradually migrate. New code should use async/await.

Action: Wrap old APIs, write new code with async/await.

Red Flags - STOP and Reconsider

  • Nested callbacks (pyramid of doom)
  • Functions that sometimes return values, sometimes Promises
  • Manual error handling with error-first callbacks
  • Mixing async/await with.then() chains unnecessarily

Common Rationalizations (All Invalid)

ExcuseReality
"Callbacks are simpler"async/await is more readable and maintainable
"Promise overhead is too high"Negligible in practice, clarity wins
"Our team knows callbacks"async/await is standard modern JavaScript

Quick Reference

PatternCallbacksasync/await
Sequential opsNested callbacksSequential await
Concurrent opsManual trackingPromise.all
Error handlingError-first conventiontry/catch
Type inferenceManual annotationsAutomatic flow
CompositionDifficultNatural

The Bottom Line

async/await produces cleaner code with better type inference.

Callbacks create pyramids of nested code where types don't flow well. Promises and async/await flatten the structure, compose naturally, handle errors with standard try/catch, and let TypeScript infer types automatically. Use async/await for all new async code.

Reference

Based on "Effective TypeScript" by Dan Vanderkam, Item 27: Use async Functions Instead of Callbacks to Improve Type Flow.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

34.87%
按下载量换算22

Claude

29.49%
按下载量换算19

Cursor

19.17%
按下载量换算12

Gemini CLI

9.59%
按下载量换算6

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills