无触发源Observable时,如何用switchMap取消NGXS中的HTTP请求?
解决方案
方法一:利用NGXS内置的Action配置(推荐)
NGXS原生支持取消未完成的同类型Action,只需在定义Fetch Action时添加cancelUncompleted: true配置,就能自动取消之前未完成的Action实例,进而中止对应的HTTP请求(Angular的HttpClient请求会在订阅取消时自动终止)。
修改后的Store Action代码:
@Action(Fetch, { cancelUncompleted: true }) private fetchFromDatabase(ctx: StateContext<StateModel>) { // 移除手动调用的.subscribe(),将Observable返回给NGXS,由框架管理订阅生命周期 return this.http.get('url').pipe( catchError(err => { ctx.dispatch(new FetchError()); return of(false); }), tap(data => { if(typeof data !== 'boolean') { ctx.dispatch(new FetchSuccess()); } }) ); }
方法二:手动维护触发流(自定义场景适用)
如果需要更灵活的逻辑控制,可以在State类中通过Subject追踪Fetch Action的触发事件,结合switchMap实现请求切换:
import { Subject, switchMap, catchError, tap, of } from 'rxjs'; import { State, Action, StateContext, Store } from '@ngxs/store'; import { HttpClient } from '@angular/common/http'; @State<StateModel>({ name: 'yourState' }) export class YourState { // 创建Subject用于触发请求流 private fetchTrigger$ = new Subject<void>(); constructor( private http: HttpClient, private store: Store ) { // 初始化请求处理流 this.initFetchStream(); } private initFetchStream(): void { this.fetchTrigger$.pipe( // 新触发时自动取消前一个未完成的请求 switchMap(() => this.http.get('url').pipe( catchError(err => { this.store.dispatch(new FetchError()); return of(false); }), tap(data => { if(typeof data !== 'boolean') { this.store.dispatch(new FetchSuccess()); } }) )) ).subscribe(); } @Action(Fetch) private fetchFromDatabase(ctx: StateContext<StateModel>): void { // 每次分发Fetch Action时,推送信号触发新请求 this.fetchTrigger$.next(); } }
内容的提问来源于stack exchange,提问作者Heribert Greinix
相关产品推荐
相关产品推荐

