RxJS嵌套subscribe如何等待两个请求完成后触发finalize
问题原因
你当前的嵌套订阅写法是RxJS典型反模式:
- 外层
pipe绑定的finalize只会感知getTemplate()这一个Observable的生命周期,完全无法识别你在subscribe回调里手动启动的createImage()独立订阅 - 当
getTemplate()请求完成、抛出返回值后,外层流就直接终止,自然会立刻触发finalize,不会等待内部嵌套的第二个请求执行完毕。
修复方案
不要在subscribe回调内开启新的独立订阅,使用RxJS高阶映射操作符将两个串行依赖的请求合并为同一个Observable流,让整个流的生命周期覆盖两个请求的全流程,finalize就会在所有请求执行完成后再触发。
- 首先调整
createImage方法,不要在方法内部直接订阅,直接返回请求对应的Observable:public createImage(link: string) { return this.service.createImage(link); } - 改造
getTemplate方法,用switchMap(单次触发场景也可以用concatMap)将第二个请求接入主流:// 记得提前导入需要的操作符 // import { of } from 'rxjs'; // import { switchMap, finalize } from 'rxjs/operators'; private getTemplate(){ this.loading = true; this.service.getTemplate() .pipe( // 拿到第一个请求结果后,映射为第二个请求的Observable switchMap(templateRes => { return templateRes?.link ? this.createImage(templateRes.link) : of(null); }), // 此时finalize绑定在整个组合流上,会等两个请求全部结束后执行 finalize(() => this.loading = false) ) .subscribe(imageRes => { if (imageRes) { this.image = imageRes; } // 错误逻辑可以统一在subscribe的第二个error回调中处理,无需分开写 }) }
补充说明
- 改造后整个流程只有一个subscribe,所有流的生命周期统一管理,不会出现提前触发finalize的问题
- 如果需要严格保证请求触发顺序、不自动取消未完成的旧请求,把
switchMap替换为concatMap即可,逻辑完全一致 - 两个请求的报错都可以在这一个subscribe的error回调中统一捕获处理,不需要分别给两个请求写错误监听
内容的提问来源于stack exchange,提问作者gerkane
相关产品推荐
相关产品推荐

