Angular异步调用问题:updateQuestions调用时机错误致变量异常
解决异步数据加载导致的updateQuestions调用时机问题
核心问题分析
你的代码中setAssessmentData是异步操作,assessmentData.securityControl需要等待接口返回后才能赋值。当前存在两个关键问题:
isAssessmentDataLoading仅在错误回调中更新,成功加载后未重置为false,导致加载状态始终异常。- 当
isControlSecurityComplete为true时,selectedSecurity通过订阅selectedSecurity$异步获取,若updateQuestions在selectedSecurity赋值前执行,会导致问题列表过滤逻辑失效;同时原逻辑未严格保证updateQuestions仅在assessmentData加载完成后触发。
具体解决方案
1. 完善加载状态管理
在setAssessmentData发起请求时标记加载状态为true,成功和错误回调中都重置为false,确保UI能正确反映数据加载状态。
2. 同步selectedSecurity与assessmentData的加载时机
先订阅selectedSecurity$确保值能及时获取,在selectedSecurity更新时,若assessmentData已加载完成且存在有效securityControl,自动触发updateQuestions。
3. 清理订阅防止内存泄漏
添加订阅数组管理所有异步订阅,在组件销毁时统一取消订阅。
修改后的代码
import { Subscription } from 'rxjs'; // 组件类中新增订阅管理数组 subscriptions: Subscription[] = []; ngOnInit() { this.isControlSecurityComplete = this.navigationService.getControlSecurityComplete(); // 先订阅selectedSecurity$,确保值更新时同步刷新问题列表 const securitySub = this.dataService.selectedSecurity$.subscribe((value) => { this.selectedSecurity = value; // 若评估数据已加载完成且存在有效安全控制,重新更新问题 if (!this.isAssessmentDataLoading && this.assessmentData.securityControl) { this.updateQuestions(this.assessmentData.securityControl); } }); this.subscriptions.push(securitySub); // 启动评估数据加载 this.setAssessmentData(this.navigationService.getSavedID()); if (this.isControlSecurityComplete) { this.questions.forEach(question => { question.selectedOption = null; }); } } setAssessmentData(assessmentID: string) { this.isAssessmentDataLoading = true; // 开始加载时标记状态 this.assessmentService.getAssessmentById(assessmentID).subscribe( (assessment) => { // 赋值评估数据 this.assessmentData.nomeAssessment = assessment['nomeAssessment']; this.assessmentData.dataAssessment = assessment['dataAssessment']; this.assessmentData.nomeStruttura = assessment['nomeStruttura']; this.assessmentData.nomeCittaOSito = assessment['nomeCittaOSito']; this.assessmentData.statoProvinciaRegione = assessment['statoProvinciaRegione']; this.assessmentData.contatti.nome = assessment['contatti']?.nome; this.assessmentData.contatti.ruolo = assessment['contatti']?.ruolo; this.assessmentData.contatti.email = assessment['contatti']?.email; this.assessmentData.selectedCategory = assessment['selectedCategory']; this.assessmentData.securityLevel = assessment['securityLevel']; this.assessmentData.securityControl = assessment['securityControl']; this.assessmentData.domande = assessment['domande']; this.assessmentData.rispostaChatGPT = assessment['rispostaChatGPT']; // 处理安全控制状态与问题更新 if (this.assessmentData.securityControl === '') { this.controlSelected = true; } else { this.controlSelected = false; // 仅当selectedSecurity已赋值时才调用updateQuestions,否则等订阅触发后自动执行 if (this.selectedSecurity !== undefined) { this.updateQuestions(this.assessmentData.securityControl); } } this.isAssessmentDataLoading = false; // 加载完成后重置状态 }, (error) => { this.isAssessmentDataLoading = false; console.error('Errore nel recupero dell\'assessment', error); } ); } updateQuestions(controlName: string) { this.dataService.getJsonDataNew(controlName).subscribe((data) => { if (data && data.fileDocument && Array.isArray(data.fileDocument.fileData)) { this.questions = data.fileDocument.fileData.filter((item: any) => item.Security <= this.selectedSecurity); } else { this.questions = []; } }); } // 组件销毁时清理所有订阅 ngOnDestroy() { this.subscriptions.forEach(sub => sub.unsubscribe()); }
关键修改说明
- 提前订阅
selectedSecurity$,确保selectedSecurity的值能及时同步,且在值变化时自动刷新问题列表(当评估数据已加载完成时)。 - 统一管理
isAssessmentDataLoading状态,避免加载状态异常。 - 添加订阅清理逻辑,防止内存泄漏。
- 在调用
updateQuestions前检查selectedSecurity是否已赋值,避免过滤逻辑因未定义值失效。
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

