如何用RxJS实现API1响应后延迟5秒调用API2且初始调用无需等待
问题
在API(1)请求得到响应后调用API(2),要求API(2)每次调用间隔5秒,且当指定条件满足时停止调用。目前已有实现代码可正常运行,但现在希望调整为:API(2)首次调用无需等待,后续调用延迟5秒执行。现有代码如下:
const iterator = new BehaviorSubject<number>(0); return this.api1.post(data).pipe( concatMap((res) => iterator.pipe( mergeMap((i) => this.api2 .get(res?.id) .pipe( tap((result: any) => { if ( result.info?.count <= 7 && result.done === false && !isNotNullOrUndefined(result.error) ) { iterator.next(i + 1); } else { const errorsDetails = { message: result.info?.stage_message, detail: result.error?.details, }; this.showToastError(errorsDetails, false); } }), takeWhile( (d) => d.info?.count <= 7 && d.done === false && !isNotNullOrUndefined(d.error), true ) ) ) ) ) );
解决方案
要实现「首次调用无延迟,后续每次间隔5秒」的效果,只需针对iterator的非首次发射添加延迟逻辑即可,具体修改如下:
修改点说明
- 借助
iterator的发射值i判断是否为首次调用:初始值0对应首次请求,后续值>=1对应延迟请求 - 首次调用直接执行API请求,后续调用先通过
timer(5000)等待5秒,再发起API请求
修改后的完整代码
const iterator = new BehaviorSubject<number>(0); return this.api1.post(data).pipe( concatMap((res) => iterator.pipe( mergeMap((i) => // 首次调用(i=0)直接请求,后续先延迟5秒 i === 0 ? this.api2.get(res?.id) : timer(5000).pipe(switchMap(() => this.api2.get(res?.id))) ), tap((result: any) => { if ( result.info?.count <= 7 && result.done === false && !isNotNullOrUndefined(result.error) ) { iterator.next(iterator.value + 1); } else { const errorsDetails = { message: result.info?.stage_message, detail: result.error?.details, }; this.showToastError(errorsDetails, false); } }), takeWhile( (d) => d.info?.count <= 7 && d.done === false && !isNotNullOrUndefined(d.error), true ) ) ) );
额外优化说明
- 原代码中
iterator.next(i + 1)替换为iterator.next(iterator.value + 1),避免依赖闭包中的i值,逻辑更直观 - 也可以用
mergeMap的第二个参数index判断:index === 0时直接请求,效果完全一致
内容的提问来源于stack exchange,提问作者De Giovanni
相关产品推荐
相关产品推荐

