如何按5秒间隔调用Observable服务最多30次且满足条件即停止
问题分析
现有代码栈溢出的核心原因是retryWhen未配置延迟和重试上限,randomNumber返回同步的of Observable,不符合条件就立刻抛出错误触发重试,短时间内产生海量调用直接撑爆调用栈。另外还存在三个要求都未满足的问题:没有限制最多30次调用、间隔5秒的逻辑位置错误、未控制subscribe回调的触发次数。
可直接运行的实现代码
import { retryWhen, delay, take, tap, first, catchError } from 'rxjs/operators'; import { of, Observable } from 'rxjs'; public randomExample() { this.randomNumber().pipe( // 重试逻辑:最多重试29次,加上首次调用总共不超过30次 retryWhen(errors => errors.pipe( tap(n => console.log('当前accuracy值高于50,5秒后重试', n)), delay(5000), // 固定间隔5秒再重试 take(29) ) ), // 只取第一个accuracy小于50的结果,匹配后直接终止流,保证subscribe仅触发一次 first(res => res.accuracy < 50), // 可选:捕获30次调用都未匹配条件的错误,避免抛出异常 catchError(() => of({ accuracy: -1, msg: '累计30次调用均未得到符合要求的结果' })) ).subscribe((res) => { console.log('最终结果:', res); }) } public randomNumber(): Observable<{accuracy:number}> { const n = Math.floor(Math.random() * 100); const value = { accuracy: n }; console.log('服务调用返回:', value); return of(value); }
功能匹配说明
- 调用次数限制:首次调用+最多29次重试,累计最多30次,超过后流自动结束
- 调用间隔:每次重试前固定等待5秒,相邻两次调用间隔符合要求
- 回调触发控制:
first操作符在拿到第一个符合要求的结果后立刻终止流,保证subscribe回调只会触发一次
内容的提问来源于stack exchange,提问作者Maccurt
相关产品推荐
相关产品推荐

