如何为API响应轮询函数设置指定时长的自定义超时?
为TypeScript轮询函数添加可配置超时限制的实现方案
问题背景
我们框架中的pollUntil函数用于轮询等待特定API响应后执行后续逻辑,但目前无超时限制。为适配某个耗时约10分钟的任务,不得不将Cucumber全局步骤超时设为900000毫秒,这会影响其他失败用例的超时判定。需要为pollUntil添加可配置的超时参数,支持不同API调用传入自定义超时值。
现有pollUntil实现:
public async pollUntil(request: () => Promise<any>,condition: (res: any) => boolean) { const responseData = await request(); const conditionResponse = condition(responseData); if (!conditionResponse) { await setTimeout(5000); await this.pollUntil(request, condition); } else { this.response = responseData; } }
调用方式:
await ApiCall.pollUntil(() => ApiCall.get(url),this.statusAbortComplete);
轮询终止条件:
private statusAbortComplete(response: any) { return !!(response.state === 'abortDone' && response.msg === 'empty'); }
实现方案
1. 调整函数参数与内部逻辑
新增可选的超时参数timeoutMs(可设置默认值),同时记录轮询开始时间,用于实时计算已耗时是否超过阈值。此外修复原代码中await setTimeout的错误用法(setTimeout不返回Promise,需封装为异步延迟函数)。
2. 修改后的完整代码
// 封装异步延迟函数,替代直接调用setTimeout private async delay(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } public async pollUntil( request: () => Promise<any>, condition: (res: any) => boolean, timeoutMs: number = 30000, // 默认超时30秒,可自定义 pollIntervalMs: number = 5000 // 轮询间隔也支持配置,可选 ) { const startTime = Date.now(); while (true) { const responseData = await request(); // 检查是否满足终止条件 if (condition(responseData)) { this.response = responseData; return; } // 检查是否超时 const elapsedTime = Date.now() - startTime; if (elapsedTime >= timeoutMs) { throw new Error(`轮询超时:已等待${elapsedTime}毫秒,超过设定阈值${timeoutMs}毫秒`); } // 等待下一次轮询 await this.delay(pollIntervalMs); } }
3. 调用示例
针对不同场景传入对应超时值,兼容原有调用方式:
// 针对10分钟的任务,传入600000毫秒超时 await ApiCall.pollUntil( () => ApiCall.get(url), this.statusAbortComplete, 600000 ); // 普通任务使用默认30秒超时 await ApiCall.pollUntil( () => ApiCall.get(anotherUrl), this.anotherCondition );
关键说明
- 将原递归逻辑改为
while循环,避免轮询次数过多导致栈溢出 - 延迟函数
delay确保可以用await正确等待轮询间隔 - 超时参数设为可选,不传入时使用默认值,无需修改原有调用代码
- 超时后主动抛出错误,上层可捕获处理,无需依赖全局超时设置
内容的提问来源于stack exchange,提问作者Madu
相关产品推荐
相关产品推荐

