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

在while循环中订阅Observable引发无限循环的技术求助

解决RxJS异步循环请求的无限循环问题

你当前的问题核心是同步while循环和异步Observable的执行时机不匹配。while是同步代码,会瞬间疯狂执行循环体,发起无数个POST请求,但这些请求的订阅回调是异步执行的——等回调触发时,while早就已经跑了N轮,testLoop、varA、varB根本没机会被更新,自然会无限循环。

用RxJS的expand算子来实现这种递归式的异步请求链,它能完美处理“用前一次请求结果决定是否发起下一次请求”的场景,再配合reduce算子收集所有返回的values。


修改后的component.ts代码

import { of, empty, Observable } from 'rxjs';
import { expand, reduce, map } from 'rxjs/operators';

// 初始参数
const initialState = {
  varA: 100,
  varB: 0,
  finalValues: [] as string[]
};

of(initialState).pipe(
  // expand:递归处理,每次用当前状态发起请求,返回新的Observable(或empty终止)
  expand(state => {
    return this.someService.sampleFunc(state.varA, state.varB).pipe(
      map(res => {
        // 收集values
        const updatedValues = [...state.finalValues, ...res.values];
        // 判断是否继续请求
        if (res.continue === 'true') {
          // 更新参数,返回新状态供下一次请求使用
          return {
            varA: res.varA,
            varB: res.varB,
            finalValues: updatedValues
          };
        } else {
          // 终止循环,返回最终状态
          return { ...state, finalValues: updatedValues };
        }
      })
    );
  }),
  // 当expand终止时,取最后一次的状态(包含所有收集的values)
  reduce((acc, curr) => curr)
).subscribe(finalState => {
  // 循环结束,拿到最终的values数组
  this.finalValues = finalState.finalValues;
  console.log('所有收集到的values:', this.finalValues);
});

代码解释

  • expand:每次接收当前状态,发起请求后返回新的状态Observable;全程保证上一次请求完成后才会发起下一次请求,完全符合顺序执行的需求。
  • reduce:把expand过程中所有的状态合并,最终只输出最后一次的状态(也就是所有values收集完成后的结果)。
  • 状态对象全程传递参数和收集的values,避免了原代码中异步变量更新失效的问题。

service.ts代码无需修改

保持你原来的sampleFunc即可:

sampleFunc(varA: number, varB: number){
    return this.http.post(url,{
        varA: varA,
        varB: varB
    })
}

验证场景

比如第5次请求返回{continue: "false"},整个流会在第5次请求完成后终止,finalValues会包含前5次请求所有的values字段内容,总共执行5次请求,完全符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:55:21