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

Angular 2/4中http.get()递归请求栈溢出问题及标准实现方案

解决RxJS递归轮询请求栈溢出问题

嘿,我来帮你搞定这个轮询请求的问题!你遇到的栈溢出是因为原来的expand实现逻辑有问题,导致无限递归了,而且完全没做请求频率控制,肯定会搞崩的😅

错误原因分析

你原来的代码里有三个关键问题:

  1. 递归永远不会终止:不管响应是什么情况,最后都返回了Observable.of(response),expand会一直重复这个过程,无限循环直接把栈撑爆。
  2. 逻辑分支没正确返回:else块里的Rx.Observable.empty()根本没return出去,等于白写,还是会走最后的return语句。
  3. 没有请求间隔:就算逻辑对了,也会疯狂发请求,既浪费资源又容易触发服务端限流。

正确的轮询实现方案

下面是适配你业务场景的标准实现,我加上了请求延迟控制,保证不会出现网络请求泛滥的情况:

import { EMPTY, timer } from 'rxjs';
import { expand, filter, switchMap } from 'rxjs/operators';

// ...

getOriginalData(url: any) {
  return this._getRequest(url).pipe(
    // 用expand实现递归轮询
    expand((response) => {
      // 这里替换成你的实际判断逻辑:比如response状态是QUEUE时继续轮询,OK时停止
      // 你原来的代码是判断uuid==null,所以也可以换成if (response.uuid == null)
      if (response.status !== 'OK') {
        // 每隔1秒发起一次请求,可根据业务调整间隔时间
        return timer(1000).pipe(
          switchMap(() => this._getRequest(url))
        );
      } else {
        // 返回EMPTY终止递归
        return EMPTY;
      }
    }),
    // 只保留最终的成功响应,过滤掉中间的QUEUE状态结果
    filter((response) => response.status === 'OK')
  );
}

private _getRequest(url: any) {
  return this._http.get(url);
}

关键细节说明

  1. 终止递归的正确方式:当响应达到最终状态(比如status === 'OK'),返回EMPTY(RxJS 6+版本)或者Rx.Observable.empty()(旧版本),告诉expand停止递归。
  2. 添加请求延迟:用timer(1000)控制轮询间隔,避免短时间内大量请求,保护服务端和你的应用。
  3. 过滤中间结果:通过filter操作符,让订阅者只拿到最终的成功响应,不用处理中间的QUEUE状态数据。
  4. Pipeable操作符:新版本RxJS推荐用pipe组合操作符,比旧的链式调用更清晰,也避免了一些兼容性问题。

这样实现后,就能优雅地轮询直到拿到最终结果,既不会栈溢出,也不会出现网络请求泛滥的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:01:56