You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API调用完成后UI中Spinner未关闭的原因排查请求

问题排查与解决方案

核心原因

你的Spinner无法消失,主要是RxJS的Observable通知机制导致的:

  • 当API调用触发error回调时,complete回调不会被执行(error属于终止性通知,一旦触发就会跳过complete阶段),导致this.isSaving = false从未执行,Spinner一直处于显示状态。
  • 即使API调用成功,若visaSuccessHandler.execute内部存在未处理的异步逻辑,也可能间接影响状态更新,但最直接的问题还是error分支未重置状态。

解决方案

方案1:在所有分支中手动重置状态

在next和error回调中都添加this.isSaving = false,确保无论请求成功还是失败,都能关闭Spinner:

public onSave() {
  this.isSaving = true;
  this.formService.entityForm.markAsPristine();
  
  this.visaSubmitHandler.execute({ application: this.formService.entityForm.value }).subscribe({
      next: (response: IApplicationCreateResponse) => {
          this.stateRehydrationService.clearStateKey(this.formService.key);
          this.visaSuccessHandler.execute({ application: response.entity });
          this.isSaving = false; // 成功后关闭Spinner
      },
      error: (response: IApplicationCreateResponse) => {
          this.formService.entityForm.markAsDirty();
          try {
              for (const error of response.errors) {
                  const propertyName = `${error.propertyName[0].toLowerCase()}${error.propertyName.slice(1)}`;
                  const control = this.formService.entityForm.get(propertyName) as AbstractControl;
                  setErrors({ serverError: error.message }, control);
              }
              this.bottomSheet.open(DisplayErrorsComponent, { data: response.errors.map(e => e.message) });
          } catch (e) {
              console.error(e);
          }
          this.isSaving = false; // 失败后关闭Spinner
      },
      complete: () => {
          this.isSaving = false; // 保险:处理Observable正常完成的情况
      }
  });
}

方案2:使用finalize操作符(更简洁)

RxJS的finalize操作符会在Observable无论完成还是出错时执行回调,适合统一处理状态重置:

import { finalize } from 'rxjs/operators';

public onSave() {
  this.isSaving = true;
  this.formService.entityForm.markAsPristine();
  
  this.visaSubmitHandler.execute({ application: this.formService.entityForm.value })
    .pipe(finalize(() => {
      this.isSaving = false; // 无论成功失败都会执行
    }))
    .subscribe({
        next: (response: IApplicationCreateResponse) => {
            this.stateRehydrationService.clearStateKey(this.formService.key);
            this.visaSuccessHandler.execute({ application: response.entity });
        },
        error: (response: IApplicationCreateResponse) => {
            this.formService.entityForm.markAsDirty();
            try {
                for (const error of response.errors) {
                    const propertyName = `${error.propertyName[0].toLowerCase()}${error.propertyName.slice(1)}`;
                    const control = this.formService.entityForm.get(propertyName) as AbstractControl;
                    setErrors({ serverError: error.message }, control);
                }
                this.bottomSheet.open(DisplayErrorsComponent, { data: response.errors.map(e => e.message) });
            } catch (e) {
                console.error(e);
            }
        }
    });
}

额外注意点

  • 确保isSaving是组件的公共属性(或通过getter暴露),模板能正确读取到状态变化。
  • 若visaSuccessHandler.execute是异步操作且需要等待它完成后再关闭Spinner,需将其转换为Observable并使用switchMap等操作符串联,避免Spinner提前关闭。

内容的提问来源于stack exchange,提问作者Christos Segkani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:57:07