如何同步调用NgRx Component Store的Effect?等待指定Effect完成后执行另一个
实现NgRx Component Store中Effect的顺序执行
要实现startAndUpdateProgress执行完成后再调用postFileToServer,核心是监听startAndUpdateProgress依赖的numbersObservable的完成事件,再触发后续上传操作。以下是两种可行方案:
方案一:通过完成信号追踪串联操作
这种方案适合需要单独触发进度更新逻辑,或需要在多个地方复用进度完成信号的场景:
- 在Component Store中添加私有Subject标记进度完成:
private progressCompleted$ = new Subject<void>();
- 修改
startAndUpdateProgress,在numbersObservable完成时发出信号:
readonly startAndUpdateProgress = this.effect<void>( (trigger$) => trigger$.pipe( exhaustMap(() => this.numbersObservable.pipe( tapResponse({ next: (progress) => this.updateIrisFileListProgress(progress), error: (error) => console.error(error) }), finalize(() => this.progressCompleted$.next()) // 进度流完成时发送信号 ) ) ) );
- 串联操作的两种实现方式:
方式A:新Effect处理串联逻辑
readonly startProgressThenPost = this.effect<FormData>( (formData$) => formData$.pipe( exhaustMap((formData) => // 先触发进度更新,再等待完成信号 this.startAndUpdateProgress.run(void 0).pipe( switchMap(() => this.progressCompleted$), take(1), // 只取一次完成信号 switchMap(() => this.schemaUploadSrvice.postFiles(formData).pipe( tapResponse({ next: () => this.updateSchemaUploadServerResponse(), error: (error: HttpErrorResponse) => console.error(error) }) ) ) ) ) ) );
方式B:组件内手动串联触发
// 组件内先启动进度更新 this.store.startAndUpdateProgress(); // 等待进度完成后触发上传 this.store.progressCompleted$.pipe( take(1) ).subscribe(() => { this.store.postFileToServer(yourFormData); });
方案二:直接在单个Effect中合并两个操作
如果不需要单独触发进度更新,只需要在上传前执行一次进度流程,可直接合并两个操作到一个Effect:
readonly startProgressThenPost = this.effect<FormData>( (formData$) => formData$.pipe( exhaustMap((formData) => this.numbersObservable.pipe( // 处理进度更新 tap((progress) => this.updateIrisFileListProgress(progress)), catchError((error) => { console.error(error); return EMPTY; // 捕获错误后终止流,避免影响后续上传 }), ignoreElements(), // 忽略进度值,只等待流完成 // 进度流完成后执行上传 switchMap(() => this.schemaUploadSrvice.postFiles(formData).pipe( tapResponse({ next: () => this.updateSchemaUploadServerResponse(), error: (error: HttpErrorResponse) => console.error(error) }) ) ) ) ) ) );
注意事项
- 确保
numbersObservable是有限流(会触发complete事件),否则后续上传操作永远不会执行。如果是无限流,需添加终止条件(比如takeUntil、take(n))手动结束流。 - 使用
exhaustMap可避免重复触发,防止同一时间多个并行的进度更新或上传操作。
内容的提问来源于stack exchange,提问作者Arindam
相关产品推荐
相关产品推荐

