如何在RxJS的finalize()中执行Observable请求或实现类似逻辑?
RxJS 链式处理两个 Observable 请求的优化实现
需求说明
需要链式处理两个类型为 Observable<void> 的请求,满足以下规则:
- 始终执行请求A
- 请求A执行完成后(无论A是否报错),必须执行请求B,类似
finalize()的行为 - 若A报错
E_A,整个流最终抛出E_A - 若A成功但B报错
E_B,整个流最终抛出E_B(也可接受流成功的情况) - 若两者均报错,整个流最终抛出
E_A
原实现方案
用户已实现的方案逻辑可行,但代码较为繁琐:
// 修改后端状态的请求,可能失败 const reqA: Observable<void> = this.mutateSystemState(); // 加载并渲染系统状态的请求 const reqB: Observable<void> = this.updateSystemStateDisplay(); const pipeline = reqA.pipe( catchError(e => of({ errA: e })), mergeMap(resultA => reqB.pipe( catchError(e => of({ errB: e })), map(resultB => { if (resultA instanceof Object) { throw resultA.errA; } else if (resultB instanceof Object) { throw resultB.errB; } }) )) );
优化后的实现方案
利用 RxJS 原生操作符组合,更简洁地实现需求逻辑:
const pipeline = reqA.pipe( // 捕获A的错误:先执行B,再抛出A的错误 catchError(errA => reqB.pipe( ignoreElements(), // 忽略B的成功输出,不影响最终抛出A的错误 concat(throwError(() => errA)) ) ), // A成功后,执行B;B的错误会直接向上抛出 concat(reqB) );
逻辑解析
- 处理A报错的情况:当A抛出错误时,
catchError会先执行reqB,通过ignoreElements()忽略B的成功结果,随后通过concat(throwError(() => errA))抛出A的错误,满足「A报错时执行B且最终抛E_A」「两者都报错时抛E_A」的要求 - 处理A成功的情况:A执行成功后,进入
concat(reqB)执行B;若B报错则直接抛出该错误,若B成功则整个流正常完成,满足「A成功后执行B」「B报错则抛E_B」的要求 - 全局规则满足:无论A成功或失败,B都会被执行,且错误优先级完全符合需求
内容的提问来源于stack exchange,提问作者Good Night Nerd Pride
相关产品推荐
相关产品推荐

