如何在TypeScript中实现类型安全的通用限流重试处理函数
类型安全的429限流重试工具实现方案
核心修改点
- 引入泛型
P extends any[]约束函数入参类型,替换原有不安全的any参数声明 - 引入泛型
T约束异步函数的返回值类型,实现返回值自动类型推导 - 补充错误类型守卫,避免catch块内滥用
any类型 - 调用时无需手动声明泛型,即可获得完整的参数校验和返回值类型提示
完整实现代码
首先补充sleep函数的基础定义(如果已有可忽略):
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
最终的类型安全重试工具实现:
// 通用HTTP错误类型定义,如果你使用Axios也可以直接替换为AxiosError type HttpError = { response: { status: number } } // 类型守卫:安全判断错误是否为带response.status的HTTP请求错误 function isHttpError(err: unknown): err is HttpError { return !!err && typeof err === 'object' && 'response' in err && !!(err as HttpError).response && typeof (err as HttpError).response === 'object' && 'status' in (err as HttpError).response && typeof (err as HttpError).response.status === 'number' } // 泛型P约束入参类型,泛型T约束返回值类型 async function throttleHandler<P extends any[], T>( promiseFunction: (...args: P) => Promise<T>, ...args: P ): Promise<T> { do { try { return await promiseFunction(...args) } catch (err: unknown) { if (isHttpError(err) && err.response.status === 429) { await sleep(300) console.log('Throttle happened, sleeping for 300ms') } else { throw err } } } while (true) }
使用示例
调用时会自动匹配传入API的参数类型和返回值类型,参数传错会直接触发TS类型报错,返回值无需额外类型断言:
// 示例API函数定义 const myApi = (arg1: string, arg2: number, arg3: boolean): Promise<{assets: string[]}> => { // 你的实际API逻辑 return Promise.resolve({assets: ['img1.png', 'img2.png']}) } // 自动推导返回值类型为 {assets: string[]},参数会自动校验类型 const res = await throttleHandler(myApi, 'test_param', 123, true)
可选优化(支持自定义配置)
如果需要灵活调整重试间隔、最大重试次数,可扩展为带配置项的版本:
async function throttleHandler<P extends any[], T>( promiseFunction: (...args: P) => Promise<T>, options: {retryDelay?: number, maxRetries?: number} = {}, ...args: P ): Promise<T> { const {retryDelay = 300, maxRetries = Infinity} = options let retryCount = 0 do { try { return await promiseFunction(...args) } catch (err: unknown) { if (isHttpError(err) && err.response.status === 429 && retryCount < maxRetries) { retryCount++ await sleep(retryDelay) console.log(`Throttle happened, retry ${retryCount}/${maxRetries}, sleeping for ${retryDelay}ms`) } else { throw err } } } while (true) }
内容的提问来源于stack exchange,提问作者Derviş Kayımbaşıoğlu
相关产品推荐
相关产品推荐

