Angular中如何确保函数调用在API1结果存入状态后执行?
问题场景
需要先调用api1并将结果存入状态管理库,待结果成功存入后再执行指定函数。现有一个selector,会返回布尔类型的Observable isLoaded——该标志会在api1调用完成且结果存入store后变为true。需确保以下代码仅在isLoaded更新为true后执行:
private someSubject: Subject<{ skip?: boolean; defer?: number }> = new Subject<{ skip?: boolean; defer?: number; }>(); private getData() { this.someSubject .asObservable() .pipe( takeUntil(this.ngUnsubscribe), switchMap(({ skip, defer }) => of(skip).pipe(delay(defer))), switchMap(skip => { if (skip) { return this.getDataAsObservable(); } }), ) .subscribe(); }
几种可行的实现方式
1. 等isLoaded首次变为true后,处理所有后续事件
如果只需要等待isLoaded第一次触发为true,之后所有someSubject的事件都正常处理,用skipUntil操作符最直接:
private getData() { this.someSubject .asObservable() .pipe( takeUntil(this.ngUnsubscribe), // 等待isLoaded变为true后,才继续处理后续数据流 skipUntil(this.store.select(yourIsLoadedSelector).pipe(filter(isLoaded => isLoaded))), switchMap(({ skip, defer }) => of(skip).pipe(delay(defer))), switchMap(skip => { if (skip) { return this.getDataAsObservable(); } // 补充:skip为false时返回空Observable,避免报错 return EMPTY; }), ) .subscribe(); }
2. 每次触发事件前,确保isLoaded处于true状态
如果担心后续isLoaded可能被重置为false,需要保证每一次someSubject事件触发时,isLoaded都是true,可以用withLatestFrom结合过滤:
private getData() { this.someSubject .asObservable() .pipe( takeUntil(this.ngUnsubscribe), // 合并当前isLoaded的状态 withLatestFrom(this.store.select(yourIsLoadedSelector)), // 只保留isLoaded为true的事件 filter(([_, isLoaded]) => isLoaded), // 剥离isLoaded状态,只保留原事件数据 map(([eventData]) => eventData), switchMap(({ skip, defer }) => of(skip).pipe(delay(defer))), switchMap(skip => { if (skip) { return this.getDataAsObservable(); } return EMPTY; }), ) .subscribe(); }
3. 不丢弃事件,等待isLoaded变为true后再处理
如果不想丢弃isLoaded为false时触发的someSubject事件,而是等isLoaded变为true后再处理这些事件,用concatMap嵌套等待逻辑:
private getData() { this.someSubject .asObservable() .pipe( takeUntil(this.ngUnsubscribe), concatMap(eventData => // 等待isLoaded变为true后,再传递当前事件数据 this.store.select(yourIsLoadedSelector).pipe( filter(isLoaded => isLoaded), first(), // 只取第一次变为true的信号,避免重复触发 map(() => eventData) ) ), switchMap(({ skip, defer }) => of(skip).pipe(delay(defer))), switchMap(skip => { if (skip) { return this.getDataAsObservable(); } return EMPTY; }), ) .subscribe(); }
补充说明
- 需要导入对应的RxJS操作符:
import { skipUntil, filter, withLatestFrom, concatMap, first, EMPTY } from 'rxjs'; - 原代码中
switchMap分支如果skip为false没有返回值,会导致运行时错误,建议补充返回EMPTY空Observable。
内容的提问来源于stack exchange,提问作者pj013
相关产品推荐
相关产品推荐

