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

Http拦截器在多条件过滤场景下失效问题排查

Http拦截器进度条异常问题

刷新页面或单条件过滤时进度条正常,但通过模态框进行多条件过滤(即使仅选价格单个条件)时,进度条启动后控制台仅打印true,始终不打印结束的false,进度条持续转动直到返回主页。
更新:请求结束后loadings.size仍保持为1。


相关代码

INTERCEPTOR TS

constructor(private loader:LoadingService) {}

intercept(
  request: HttpRequest<unknown>,
  next: HttpHandler
): Observable<HttpEvent<unknown>> {
  this.loader.handle(request.url, true);
  return next
    .handle(request)
    .pipe(
      catchError((error: any) => {
        console.log(error);
        this.loader.handle(error.url, true);
        return error;
      })
    )
    .pipe(
      map((evt: any) => {
        if (evt instanceof HttpResponse) {
          this.loader.handle(evt.url!, false);
        }
        return evt;
      })
    );
}

Loading Service

loadingEmitter: Subject<boolean> = new Subject<boolean>();
loadings: Map<string, boolean> = new Map<string, boolean>();

constructor() {}

handle(url: string, loadingStatus: boolean): void {
  if (loadingStatus) {
    this.loadings.set(url, loadingStatus);
    this.loadingEmitter.next(true);
  } else if (!loadingStatus && this.loadings.has(url)) {
    this.loadings.delete(url);
  }

  if (this.loadings.size == 0) {
    this.loadingEmitter.next(false);
  }
}

查询参数过滤页面代码

cards!: any[];
constructor( private route:ActivatedRoute,private filterS:FilterServiceService) {}

ngOnInit(): void {
  this.route.queryParams.subscribe((params) => {
    if (params['Id']) {
      this.filterS.filterByCategoryId(params['Id']).subscribe((response:any) => this.cards = response);
    } else {
      this.filterS.getByAllCategory(params).subscribe((response:any) => this.cards = response)
    }
  });
}

问题根源与修复方案

核心问题

  1. 错误处理逻辑错误:请求出错时调用this.loader.handle(error.url, true),相当于给同一个URL重复添加加载状态,后续仅删除一次会导致loadings残留条目。
  2. 状态结束逻辑不完整:仅在请求成功返回HttpResponse时处理结束状态,错误场景下不会触发删除操作,导致loadings只增不减。
  3. 不支持相同URL并发请求:Map<string, boolean>会被覆盖,并发请求结束后状态处理混乱。

修复后的代码

修改后的INTERCEPTOR TS

import { throwError } from 'rxjs';
import { finalize } from 'rxjs/operators';

constructor(private loader: LoadingService) {}

intercept(
  request: HttpRequest<unknown>,
  next: HttpHandler
): Observable<HttpEvent<unknown>> {
  const requestUrl = request.url;
  this.loader.handle(requestUrl, true);
  
  return next.handle(request).pipe(
    catchError((error: any) => {
      console.log(error);
      return throwError(() => error);
    }),
    finalize(() => {
      // 无论成功/失败,统一结束该URL的加载状态
      this.loader.handle(requestUrl, false);
    })
  );
}

修改后的Loading Service

loadingEmitter: Subject<boolean> = new Subject<boolean>();
// 改用计数存储,支持相同URL的并发请求
loadings: Map<string, number> = new Map<string, number>();

constructor() {}

handle(url: string, loadingStatus: boolean): void {
  if (loadingStatus) {
    // 启动请求时计数+1
    const currentCount = this.loadings.get(url) || 0;
    this.loadings.set(url, currentCount + 1);
    this.loadingEmitter.next(true);
  } else {
    // 结束请求时计数-1,减至0则删除条目
    const currentCount = this.loadings.get(url) || 0;
    if (currentCount > 1) {
      this.loadings.set(url, currentCount - 1);
    } else {
      this.loadings.delete(url);
    }
  }

  // 根据是否还有未完成请求,发送对应状态
  this.loadingEmitter.next(this.loadings.size > 0);
}

优化查询参数页面(避免内存泄漏)

import { Subject, takeUntil } from 'rxjs';

cards!: any[];
private destroy$ = new Subject<void>();

constructor( private route: ActivatedRoute, private filterS: FilterServiceService) {}

ngOnInit(): void {
  this.route.queryParams.pipe(
    takeUntil(this.destroy$)
  ).subscribe((params) => {
    if (params['Id']) {
      this.filterS.filterByCategoryId(params['Id']).subscribe((response: any) => this.cards = response);
    } else {
      this.filterS.getByAllCategory(params).subscribe((response: any) => this.cards = response)
    }
  });
}

ngOnDestroy(): void {
  this.destroy$.next();
  this.destroy$.complete();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:50:32