在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
相关产品推荐
相关产品推荐

