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

Angular中MSALService登录请求无法触发LoaderService加载组件问题

问题描述

我正在开发一款需使用微软凭证登录的Angular应用,同时使用Http拦截器在HttpClient发起请求时显示加载组件。当前问题是:登录时MSALService发起的请求无法触发加载组件,应用在MSAL配置请求完成前看似处于冻结状态。

拦截器代码

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {finalize} from 'rxjs/operators';
import {LoaderService} from './loader.service';
import { HttpEvent, HttpHeaders,HttpHandler, HttpInterceptor, HttpRequest, HttpClient,HttpParams,HttpResponse,HttpErrorResponse } from '@angular/common/http';


@Injectable({
  providedIn: 'root'
})
export class InterceptorService implements HttpInterceptor {
  service_count = 0; // initialize the counter.

  constructor(public loaderService: LoaderService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.service_count++;

    this.loaderService.is_loading.next(true);
    return next.handle(req).pipe(
      finalize(
        () => {
          this.service_count--;
          if (this.service_count === 0) {
            this.loaderService.is_loading.next(false);
          }
        }
      )
    );
  }
}

Loader Service代码

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

@Injectable({
  providedIn: 'root'
})
export class LoaderService {
  public is_loading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

  constructor() { }
}
解决方案

MSAL Service内部发起的请求并未通过Angular的HttpClient,而是直接使用浏览器原生的fetch或XMLHttpRequest,因此Http拦截器无法捕获这些请求。可通过以下两种方式解决:

方式一:监听MSAL生命周期事件

MSAL Angular提供了生命周期事件,通过订阅这些事件可控制加载组件的显示与隐藏:

  1. 在登录组件或核心模块中注入MsalService并订阅事件:
import { MsalService, EventType } from '@azure/msal-angular';

constructor(private msalService: MsalService, private loaderService: LoaderService) {
  this.msalService.instance.addEventCallback((event) => {
    // 登录/获取令牌请求开始时显示加载
    if (event.eventType === EventType.LOGIN_START || event.eventType === EventType.ACQUIRE_TOKEN_START) {
      this.loaderService.is_loading.next(true);
    }

    // 请求结束(成功/失败)时隐藏加载
    const endEvents = [
      EventType.LOGIN_SUCCESS,
      EventType.LOGIN_FAILURE,
      EventType.ACQUIRE_TOKEN_SUCCESS,
      EventType.ACQUIRE_TOKEN_FAILURE
    ];
    if (endEvents.includes(event.eventType)) {
      this.loaderService.is_loading.next(false);
    }
  });
}
  1. 组件销毁时取消订阅,避免内存泄漏:
import { Subscription } from 'rxjs';

private eventSubscription?: Subscription;

ngOnInit(): void {
  this.eventSubscription = this.msalService.instance.addEventCallback((event) => {
    // 上述事件处理逻辑
  });
}

ngOnDestroy(): void {
  this.eventSubscription?.unsubscribe();
}

方式二:自定义MSAL的HTTP客户端

让MSAL请求通过Angular的HttpClient发送,这样拦截器就能正常捕获请求:

  1. 创建自定义HTTP客户端类,实现IMsalHttpClient:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { IMsalHttpClient } from '@azure/msal-angular';

@Injectable()
export class CustomMsalHttpClient implements IMsalHttpClient {
  constructor(private httpClient: HttpClient) {}

  sendRequest<T>(url: string, options: any): Promise<T> {
    return this.httpClient.request(options.method || 'GET', url, options).toPromise();
  }
}
  1. 在app.module.ts中配置MSAL时替换默认HTTP客户端:
import { MsalModule, IMsalHttpClient } from '@azure/msal-angular';
import { CustomMsalHttpClient } from './custom-msal-http-client';

@NgModule({
  imports: [
    MsalModule.forRoot({
      auth: {
        clientId: '你的客户端ID',
        authority: '你的权限地址',
        redirectUri: '你的重定向URI'
      }
    })
  ],
  providers: [
    { provide: IMsalHttpClient, useClass: CustomMsalHttpClient }
  ]
})
export class AppModule { }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:06:27