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

如何在AngularJS中实现多HTTP请求进度条与页面加载进度显示

我太懂你这种烦恼了!第三方加载进度条插件时不时掉链子,尤其是连续发起好几个请求的时候,进度条直接“失踪”,完全不靠谱。既然你已经了解HTTP拦截器的基本原理,那咱们自己动手实现一个稳定可控的方案,再也不用看插件脸色!

实现基于HTTP Interceptor的加载进度条

1. 核心思路:用拦截器精准追踪请求生命周期

HTTP拦截器可以捕获所有请求的发起、响应完成(包括失败)事件,我们可以用一个服务来维护当前活跃的请求数量,再根据这个数量计算进度,或者控制进度条的显示与更新——完全自己掌控,再也不会出现进度条跳票的情况!

2. 第一步:创建进度管理服务

先搞一个专门的服务,负责追踪请求数量、计算进度值,并且通过RxJS的Subject把进度状态发送给UI组件:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class LoadingProgressService {
  private activeRequests = 0;
  private progressSubject = new BehaviorSubject<number>(0);
  public progress$: Observable<number> = this.progressSubject.asObservable();

  // 发起新请求时调用
  startRequest(): void {
    this.activeRequests++;
    // 初始进度设为20%,避免一直卡在0的尴尬
    this.updateProgress(20);
  }

  // 请求结束(成功/失败都算)时调用
  endRequest(): void {
    this.activeRequests--;
    if (this.activeRequests <= 0) {
      this.activeRequests = 0;
      // 最后直接拉满到100%,给用户明确的完成反馈
      this.updateProgress(100);
      // 延迟重置进度,让用户能看到完成的动画
      setTimeout(() => {
        this.progressSubject.next(0);
      }, 300);
    } else {
      // 根据剩余活跃请求数计算进度,这里做了简单的线性分配
      const progress = 20 + (80 * (1 - this.activeRequests / 10)); // 假设最多同时10个请求,可按需调整
      this.updateProgress(Math.min(Math.round(progress), 90)); // 最多到90%,留到最后一步拉满
    }
  }

  private updateProgress(value: number): void {
    this.progressSubject.next(value);
  }

  // 可选:手动重置进度(比如路由切换时)
  reset(): void {
    this.activeRequests = 0;
    this.progressSubject.next(0);
  }
}

3. 第二步:实现HTTP拦截器

在拦截器里调用上面的服务,拦截所有请求的开始和结束:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { LoadingProgressService } from './loading-progress.service';

@Injectable()
export class LoadingProgressInterceptor implements HttpInterceptor {

  constructor(private loadingProgressService: LoadingProgressService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // 可以跳过不需要显示进度的请求,比如静态资源、OPTIONS预检请求
    if (request.url.includes('assets/') || request.method === 'OPTIONS') {
      return next.handle(request);
    }

    // 请求发起时通知服务
    this.loadingProgressService.startRequest();

    // 用finalize确保无论请求成功失败,都通知服务结束
    return next.handle(request).pipe(
      finalize(() => {
        this.loadingProgressService.endRequest();
      })
    );
  }
}

别忘了在app.module.ts里注册这个拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoadingProgressInterceptor } from './loading-progress.interceptor';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: LoadingProgressInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }

4. 第三步:创建进度条UI组件

现在把进度状态渲染成直观的顶部进度条:

<div class="loading-progress" *ngIf="(progress$ | async) > 0">
  <div class="loading-progress-bar" [style.width.%]="progress$ | async"></div>
</div>

对应的CSS:

.loading-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-color: #f0f0f0;
  z-index: 9999;
}

.loading-progress-bar {
  height: 100%;
  background-color: #1976d2; /* Angular主题色,可按需修改 */
  transition: width 0.2s ease-in-out;
}

组件逻辑:

import { Component } from '@angular/core';
import { LoadingProgressService } from './loading-progress.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-loading-progress',
  templateUrl: './loading-progress.component.html',
  styleUrls: ['./loading-progress.component.css']
})
export class LoadingProgressComponent {
  progress$: Observable<number>;

  constructor(private loadingProgressService: LoadingProgressService) {
    this.progress$ = this.loadingProgressService.progress$;
  }
}

最后把这个组件加到app.component.html的最顶部,就能全局生效啦!

5. 可选优化点

  • 页面级进度:配合路由守卫,进入新页面时调用reset()重置进度,实现单个页面的请求进度追踪。
  • 精准进度计算:如果能提前知道当前页面的请求总数,可以在服务里记录初始总请求数,进度计算会更平滑。
  • 动画增强:给进度条添加完成时的淡出动画,或者不同状态的颜色变化(比如加载中蓝色,完成时绿色)。

这个方案完全自定义,每一个请求的生命周期都被精准控制——不管是5个还是10个请求,进度条都会按预期更新,再也不会出现“失踪”的情况!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:02:27