You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript如何用supertest每分钟轮询GET接口直到返回ready状态

你当前代码的核心问题

你写的轮询逻辑无法正常运行,存在几个硬伤:

  • 自定义的delay如果是异步方法,你没加await,实际不会等待1分钟,会以最高频发起请求,直接把服务压挂
  • 状态取值路径写错了,对照你给出的返回示例,状态字段是嵌套在body.state.state下,你直接取response.body.state拿到的是对象,永远不等于字符串ready,会直接触发死循环
  • 没做大小写兼容,你自己提到接口可能返回大写开头的Ready,直接全等匹配会判定失败
  • 没有超时兜底,万一服务启动失败卡在sending data或者validating阶段,代码会无限循环跑下去,永远无法终止
  • 没有错误处理,某一次请求遇到网络波动、返回5xx,代码会直接抛错中断,不会继续重试
  • 用var声明变量,存在作用域污染问题,TS环境下不推荐使用
TypeScript 可直接落地的实现

首先定义类型安全的延迟工具方法:

const delay = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));

轮询逻辑直接适配supertest + cucumber的使用场景:

When(/^service is up and running$/, async () => {
    // 可根据实际场景调整配置
    const POLL_INTERVAL = 60000; // 轮询间隔1分钟
    const MAX_WAIT_DURATION = 10 * 60 * 1000; // 最长等待10分钟,比预期的7分钟启动时长留足冗余
    const startTimestamp = Date.now();
    let lastKnownState = '';
    let lastRequestError = '';

    while (Date.now() - startTimestamp < MAX_WAIT_DURATION) {
        try {
            const response = await request
                .get('/api/status/')
                .set('Accept', 'application/json')
                .auth('user', 'password')
                .timeout(10000); // 单次请求10秒超时,避免某一次请求卡死后整个流程挂住

            // 可选链判空+统一转小写,兼容接口结构异常和返回值大小写差异
            const currentState = response.body?.state?.state?.toLowerCase?.() ?? '';
            lastKnownState = currentState;

            if (currentState === 'ready') {
                console.log('Service is fully ready');
                return;
            }

            console.log(`Service current state: ${currentState}, msg: ${response.body?.state?.msg ?? 'no msg'}, retry after 1 minute`);
        } catch (err) {
            lastRequestError = err instanceof Error ? err.message : String(err);
            console.log(`Fetch status failed: ${lastRequestError}, retry after 1 minute`);
        }

        // 必须加await,保证轮询间隔严格生效
        await delay(POLL_INTERVAL);
    }

    // 超时直接抛错终止流程,避免死循环
    throw new Error(`Service not ready after 10 minutes, last state: ${lastKnownState}, last error: ${lastRequestError}`);
});
实现要点说明
  • 所有异步调用都显式加了await,轮询间隔严格按配置执行,不会出现无意义的高频请求
  • 取值用可选链做了多层判空,就算接口临时返回异常结构,也不会报Cannot read property of undefined的错误
  • 状态值统一转小写比对,兼容Ready/READY/ready各种大小写返回场景
  • 加了最长等待时长兜底,超时直接抛错终止流程,不会出现无限循环
  • 单次请求设置了独立超时,不会因为某一次请求卡死导致整个轮询挂住
  • 异常场景做了捕获,网络波动、接口临时报错不会中断轮询,会按间隔继续重试
  • 所有变量用let/const声明,没有var的作用域问题,符合TS编码规范
  • 加了必要的日志输出,排查问题的时候可以直接看到每一轮轮询的状态、报错信息,不需要额外加断点调试

内容的提问来源于stack exchange,提问作者Wicky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:34:04