Angular 2/4中http.get()递归请求栈溢出问题及标准实现方案
解决RxJS递归轮询请求栈溢出问题
嘿,我来帮你搞定这个轮询请求的问题!你遇到的栈溢出是因为原来的expand实现逻辑有问题,导致无限递归了,而且完全没做请求频率控制,肯定会搞崩的😅
错误原因分析
你原来的代码里有三个关键问题:
- 递归永远不会终止:不管响应是什么情况,最后都返回了
Observable.of(response),expand会一直重复这个过程,无限循环直接把栈撑爆。 - 逻辑分支没正确返回:
else块里的Rx.Observable.empty()根本没return出去,等于白写,还是会走最后的return语句。 - 没有请求间隔:就算逻辑对了,也会疯狂发请求,既浪费资源又容易触发服务端限流。
正确的轮询实现方案
下面是适配你业务场景的标准实现,我加上了请求延迟控制,保证不会出现网络请求泛滥的情况:
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); }
关键细节说明
- 终止递归的正确方式:当响应达到最终状态(比如
status === 'OK'),返回EMPTY(RxJS 6+版本)或者Rx.Observable.empty()(旧版本),告诉expand停止递归。 - 添加请求延迟:用
timer(1000)控制轮询间隔,避免短时间内大量请求,保护服务端和你的应用。 - 过滤中间结果:通过
filter操作符,让订阅者只拿到最终的成功响应,不用处理中间的QUEUE状态数据。 - Pipeable操作符:新版本RxJS推荐用
pipe组合操作符,比旧的链式调用更清晰,也避免了一些兼容性问题。
这样实现后,就能优雅地轮询直到拿到最终结果,既不会栈溢出,也不会出现网络请求泛滥的问题啦!
内容的提问来源于stack exchange,提问作者Am Novice
相关产品推荐
相关产品推荐

