问题
TypeScript 生态中的大多数弹性库都与 HTTP 客户端绑定(axios-retry、p-retry、Polly.js),或者需要将函数包装在带有 .execute() 仪式的类中。如果你只是想在不引入重度依赖的情况下,为 任意 异步函数——数据库查询、内部服务调用、文件操作——添加重试逻辑、超时和熔断器,该怎么办?
欢迎使用 houhou。
什么是 houhou?
Houhou 是一个零依赖的 TypeScript 库(约 500 行代码),可为任意异步函数添加可组合的弹性策略。被包装的函数保留 完全相同的签名 —— 你可以像调用原始函数一样调用它。
import { task } from 'houhou'
const charge = task(chargeCard)
.retry(3)
.timeout(10_000)
.fallback(() => ({ status: 'pending' }))
await charge(account, amount)
进入全屏模式 退出全屏模式
策略一览
重试
失败时重新执行,使用固定或指数退避:
task(fetchUser).retry(3) // 简写
task(fetchUser).retry({
attempts: 5,
backoff: 'exponential',
jitter: true,
delay: 500
})
进入全屏模式 退出全屏模式
超时
如果函数未在指定时间内完成,则拒绝:
task(fetchUser).timeout(5000)
进入全屏模式 退出全屏模式
降级
失败时运行替代函数:
task(fetchUser).fallback(() => loadFromCache(id))
进入全屏模式 退出全屏模式
熔断器
防止对不健康服务重复调用:
task(queryDb).circuitBreaker({
failureThreshold: 5,
successThreshold: 2,
resetTimeout: 30_000
})
进入全屏模式 退出全屏模式
延迟
执行前等待:
task(syncData).delay(1000)
进入全屏模式 退出全屏模式
策略顺序很重要
策略是 嵌套 的:最后调用的方法包装前面的方法。执行顺序与声明顺序相反。
task(fn).retry(3).timeout(1000)
// → 超时包装重试
// → 函数运行 → 失败时重试(最多 3 次)→ 总超时 1 秒
// → 如果超时触发,则不再重试
进入全屏模式 退出全屏模式
task(fn).timeout(1000).retry(3)
// → 重试包装超时
// → 函数运行 → 1 秒超时 → 如果超时触发,重试会捕获它
// → 整个周期重复最多 3 次
进入全屏模式 退出全屏模式
类型安全 — 策略锁定
每个方法都是 可锁定的。TypeScript 在编译时防止重复配置同一策略,运行时的 Set 守卫也会强制执行:
const t = task(fn).retry(3)// @ts-expect-error — 'retry' 已被锁定
t.retry(2) // 运行时也会抛出异常
进入全屏模式 退出全屏模式
使用 AbortSignal 取消
Houhou 使用 AbortController 在超时时或提供外部信号时取消操作。AbortSignal 作为 最后一个参数 传递给你的函数:
const fn = (url: string, signal?: AbortSignal) => fetch(url, { signal })
task(fn).timeout(5000)('https://api.example.com')
// → 超时触发 → controller.abort() → fetch 被取消
进入全屏模式 退出全屏模式
你也可以传递自己的外部信号:
const controller = new AbortController()
const promise = task(fn).timeout(5000).retry(3)('url', controller.signal)
controller.abort() // 取消所有操作
进入全屏模式 退出全屏模式
组合示例
策略可以按任意顺序流畅地链式调用:
const resilient = task(callApi)
.retry({ attempts: 3, backoff: 'exponential' })
.timeout(5000)
.fallback(loadFromCache)
.circuitBreaker({ failureThreshold: 5, successThreshold: 2, resetTimeout: 30_000 })
.delay(100)
进入全屏模式 退出全屏模式
名称由来
"houhou" 在日语中意为 "方法" 或 "做法" —— 非常适合描述 如何 执行你的函数的库。
立即尝试
npm install houhou
# 或
pnpm add houhou
yarn add houhou
进入全屏模式 退出全屏模式
GitHub: https://github.com/smokeeaasd/houhou
npm: https://npmjs.com/package/houhou
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.