异步搜索请求提前显示无结果,如何判断所有异步调用完成?
解决方案
核心思路是分离“实时更新结果”和“最终无结果判断”:每个异步请求完成后立即更新页面数据,同时跟踪所有请求的完成状态,只有当所有请求都结束且总结果数为0时,才显示“未找到结果”。
步骤1:调整状态变量
新增两个职责明确的状态变量,替代原有的isBusy:
// 标记是否还有请求在处理中 isLoading = false; // 标记所有请求完成后是否无任何结果 hasNoResults = false;
步骤2:改造loadResults方法
利用RxJS的forkJoin监听所有请求完成,同时用tap操作符在每个请求完成时实时更新数据:
private loadResults(): void { if (!this.query || !this.selectedOperatingCompanyIds) { return; } // 初始化状态与结果数据 this.isLoading = true; this.hasNoResults = false; this.results = 0; this.freelancers = []; this.assignments = []; this.principals = []; this.managers = []; this.bills = []; this.users = []; this.intermediaries = []; this.operatingCompanyUsers = []; this.principalUsers = []; this.intermediaryUsers = []; // 封装所有搜索请求,每个请求完成时实时更新对应数据 const requests = [ this.repository.searchFreelancers(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.freelancers = model; this.results += model.length; }) ), this.repository.searchAssignments(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.assignments = model; this.results += model.length; }) ), this.repository.searchPrincipals(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.principals = model; this.results += model.length; }) ), this.repository.searchManagers(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.managers = model; this.results += model.length; }) ), this.repository.searchBills(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.bills = model; this.results += model.length; }) ), this.repository.searchUsers(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.users = model; this.results += model.length; this.principalUsers = model.filter(u => u.roleId == 2); this.intermediaryUsers = model.filter(u => u.roleId == 7); }) ), this.repository.searchIntermediaries(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.intermediaries = model; this.results += model.length; }) ), this.repository.searchOperatingCompanyUsers(this.query, this.selectedOperatingCompanyIds).pipe( tap(model => { this.operatingCompanyUsers = model; this.results += model.length; }) ) ]; // 监听所有请求完成事件 forkJoin(requests).subscribe({ complete: () => { this.isLoading = false; // 所有请求完成后才判断是否无结果 this.hasNoResults = this.results === 0; }, error: () => { // 处理请求错误,标记加载结束 this.isLoading = false; } }); }
步骤3:调整页面模板逻辑
根据新状态变量控制页面显示:
<!-- 加载中状态 --> <div *ngIf="isLoading">加载中...</div> <!-- 无结果状态(仅所有请求完成后显示) --> <div *ngIf="!isLoading && hasNoResults">未找到结果</div> <!-- 结果列表 --> <div *ngIf="!isLoading && !hasNoResults"> <div *ngIf="freelancers.length">自由职业者:{{ freelancers.length }}条</div> <div *ngIf="assignments.length">任务:{{ assignments.length }}条</div> <div *ngIf="principals.length">委托人:{{ principals.length }}条</div> <!-- 其他结果模块依次类推 --> </div>
关键说明
forkJoin会等待所有传入的Observable完成后才触发回调,确保我们在所有搜索请求结束后才判断是否无结果。tap操作符允许每个请求完成时立即更新页面数据,满足“尽快展示已有结果”的需求。- 拆分
isLoading和hasNoResults变量,彻底避免了“请求未完成就误判无结果”的视觉bug。
内容的提问来源于stack exchange,提问作者FllnAngl
相关产品推荐
相关产品推荐

