Angular问题:如何等待内部订阅完成后再执行指定方法
问题解决:Angular中确保内部订阅完成后执行后续方法
问题描述
我有以下Angular函数:
observeDiaryCreate(){ this.diarySub = this.diaryService.diaryTrigger$.subscribe((dataVal: boolean) => { if(dataVal) { if(this.isEdit && this.statusId != 1) { this.baseService.checkFeature('setFeature').subscribe((response: any) => { if(!response) { if((JSON.stringify(data1) !== JSON.stringify(data2))) { this.modafRef = this.modalService.show(); return; } } }, error => {}, () => {}); } this.validateDiary(); } else { this.onCancel(); } }) }
我希望仅在内部subscribe执行完成后,再执行this.validateDiary()方法。现在的问题是return和this.validateDiary()都会被执行,甚至this.validateDiary()会在内部subscribe完成前就被调用,请问该如何修改?
解决方案
问题核心是Observable订阅是异步执行的,内部this.baseService.checkFeature()的订阅还没走完,外部的this.validateDiary()就已经同步执行了。下面提供两种修改方案:
方案一:用RxJS操作符优化(推荐,避免嵌套订阅)
利用switchMap、tap、finalize等操作符整合异步流,保证执行顺序:
import { EMPTY } from 'rxjs'; import { switchMap, tap, finalize } from 'rxjs/operators'; observeDiaryCreate(){ this.diarySub = this.diaryService.diaryTrigger$.pipe( switchMap((dataVal: boolean) => { // 处理dataVal为false的分支 if (!dataVal) { this.onCancel(); return EMPTY; } // 不需要执行checkFeature的情况,直接调用validate if (!this.isEdit || this.statusId === 1) { this.validateDiary(); return EMPTY; } // 执行checkFeature并控制后续逻辑 return this.baseService.checkFeature('setFeature').pipe( // 处理弹窗逻辑 tap((response: any) => { if (!response && JSON.stringify(data1) !== JSON.stringify(data2)) { this.modafRef = this.modalService.show(); } }), // 无论成功失败,都在流结束后执行validate finalize(() => this.validateDiary()) ); }) ).subscribe({ error: () => {}, complete: () => {} }); }
方案二:调整嵌套订阅的回调位置(简单直接)
把this.validateDiary()移到内部订阅的complete回调中,同时在不需要内部订阅的分支里直接调用:
observeDiaryCreate(){ this.diarySub = this.diaryService.diaryTrigger$.subscribe((dataVal: boolean) => { if(dataVal) { if(this.isEdit && this.statusId != 1) { this.baseService.checkFeature('setFeature').subscribe((response: any) => { if(!response) { if((JSON.stringify(data1) !== JSON.stringify(data2))) { this.modafRef = this.modalService.show(); } } }, error => {}, () => { // 内部订阅完成后执行validate this.validateDiary(); }); } else { // 不需要内部异步操作,直接执行 this.validateDiary(); } } else { this.onCancel(); } }) }
内容的提问来源于stack exchange,提问作者vamsi
相关产品推荐
相关产品推荐

