Angular12全局loader拦截器工作异常不显示加载动画如何排查?
问题排查与修复方案
核心问题点
1. 订阅位置错误导致状态丢失
你把isLoading的订阅放在了ngAfterContentChecked生命周期钩子中,这个钩子会在每次Angular执行变化检测时重复触发,每次触发都会新增一个订阅:
- 当拦截器触发
showLoader发送true时,layout组件此时还没有建立订阅,收不到这个值 - 后续订阅创建时,BehaviorSubject只会返回当前最新值,如果请求已经执行完调用了
hideLoader,最新值就是false,所以你始终拿不到true - 重复订阅还会造成严重的内存泄漏问题
2. 拦截器未注册(高频遗漏项)
Angular的HTTP拦截器不会自动生效,你需要在对应模块(通常是AppModule)的providers数组中声明注册才会被调用。
修复步骤
步骤1:调整订阅逻辑
推荐直接使用Angular异步管道自动管理订阅,无需手动处理订阅销毁和变化检测:
修改layout.component.ts:
// 直接声明为Observable,移除原有手动订阅逻辑 isLoading$ = this.us.isLoading;
修改layout.component.html绑定:
<cl-spinner [show]="isLoading$ | async"></cl-spinner>
如果要手动订阅,参考如下写法:
import { Subject, takeUntil } from 'rxjs'; export class LayoutComponent { private destroy$ = new Subject<void>(); isLoading = false; ngOnInit() { this.us.isLoading .pipe(takeUntil(this.destroy$)) .subscribe((val: boolean) => { console.log('value from subscriber : ', val) this.isLoading = val; }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } }
步骤2:注册拦截器
在AppModule的providers中添加拦截器声明:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { LoaderInterceptor } from './loader.interceptor'; @NgModule({ // 其他模块配置保持不变 providers: [ { provide: HTTP_INTERCEPTORS, useClass: LoaderInterceptor, multi: true } ] }) export class AppModule { }
可选优化:兼容多并行请求场景
如果存在多个并行请求,原有逻辑会出现多次触发显示/隐藏的问题,可添加计数器优化:
修改util.service.ts:
private loadingCount = 0; isLoading = new BehaviorSubject<boolean>(false); showLoader() { this.loadingCount++; this.isLoading.next(this.loadingCount > 0); } hideLoader() { this.loadingCount = Math.max(0, this.loadingCount - 1); this.isLoading.next(this.loadingCount > 0); }
内容的提问来源于stack exchange,提问作者Fahad Subzwari
相关产品推荐
相关产品推荐

