NgRx Component Store Effect中如何统一分发请求后的Action?
解决方案
你遇到的问题是因为finalize操作符的位置不对——Component Store的Effect流在HTTP请求成功完成后,外部流的finalize未被正确触发。只需将finalize移到mergeMap内部的HTTP请求流管道中,就能实现无论请求成功或失败都分发myAction的需求,无需重复编写tap和catchError逻辑。
修正后的代码
import { ComponentStore } from '@ngrx/component-store'; import { of } from 'rxjs'; import { mergeMap, finalize } from 'rxjs/operators'; @Injectable() export class DashboardStore extends ComponentStore<T> { /** some code */ readonly disconnect = this.effect<void>( pipe( mergeMap(() => // 将finalize放到内部请求流的管道中 this.myService.doSomething().pipe( finalize(() => this.store.dispatch(myAction())) ) ), catchError((error) => { // 可选:在这里处理错误日志等逻辑 // 返回空流确保Effect不会因错误终止 return of(null); }) ) ); }
原理说明
finalize操作符会在Observable流终止时触发,无论是正常完成还是抛出错误。将它放在mergeMap内部的HTTP请求流中,就能精准绑定请求的生命周期。catchError返回of(null)是为了避免Effect因未处理的错误而终止,确保后续还能正常触发该Effect。
替代方案(复用分发逻辑)
如果不想用finalize,也可以将分发动作抽成独立函数,避免重复代码:
import { ComponentStore } from '@ngrx/component-store'; import { of } from 'rxjs'; import { mergeMap, tap } from 'rxjs/operators'; @Injectable() export class DashboardStore extends ComponentStore<T> { /** some code */ private dispatchMyAction = () => this.store.dispatch(myAction()); readonly disconnect = this.effect<void>( pipe( mergeMap(() => this.myService.doSomething()), tap(this.dispatchMyAction), catchError((error) => { this.dispatchMyAction(); return of(null); }) ) ); }
内容的提问来源于stack exchange,提问作者TCH
相关产品推荐
相关产品推荐

