【问题标题】:RXJS/Angular Replace ObservableRXJS/Angular 替换 Observable
【发布时间】:2025-12-21 15:50:16
【问题描述】:

在角度拦截器中,我想检查是否存在身份验证令牌。如果不是,则应刷新并重新发送请求。

return next.handle(authReq).pipe(map((result: any) => {
  if (result.body && result.body.error) {
    if (result.body.error === 'ERR_TOKEN_EXPIRED' || result.body.error === 'ERR_TOKENS_DO_NOT_MATCH') {
      console.log('Token is expired or invalid, refreshing.', result.body.error);

      return this.userService.refreshLoginToken().subscribe(success => {
        if (success) {
          return this.intercept(req, next);
        }
      });
    }
  }
  return result;
}));

问题是我不知道如何将 next.handle() 返回的原始 Observable 替换为新的。 this.userService.refreshLoginToken().subscribe() 之前的 return 语句返回一个 Subscription 对象。如果我只是通过管道传递refreshLoginToken() 的结果,它将无法正常工作,因为 refreshLoginToken 会发送一个 httprequest,该请求仅在订阅时执行。

要将问题简化为一行: 如何将第 1 行中由 next.handle() 返回的 Observable 替换为 this.intercept(req, next) 返回的 Observable?

谢谢!

【问题讨论】:

标签: angular rxjs angular-httpclient angular-http-interceptors rxjs-observables


【解决方案1】:

我认为你应该采取不同的方式。

请查看以下示例和最新的switchMap

import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {StoreState} from '@core/store';
import {select, Store} from '@ngrx/store';
import {getAuthToken} from '@v2/core/store/auth/auth.reducer';
import {iif, Observable, of} from 'rxjs';
import {switchMap, take} from 'rxjs/operators';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(protected readonly store: Store<StoreState>) {}

    public intercept(request: HttpRequest<void>, next: HttpHandler): Observable<HttpEvent<void>> {
        return this.store.pipe(
            select(getAuthToken),
            take(1),
            switchMap(token =>
                iif(
                    () => !token,
                    of(request),
                    of(
                        request.clone({
                            setHeaders: {
                                Authorization: `Bearer ${token?.accessToken}`,
                            },
                        }),
                    ),
                ),
            ),
            switchMap(clonedRequest => next.handle(clonedRequest)),
        );
    }
}

【讨论】:

  • 谢谢!当原始 http observable 完成时,of() 创建的 observables 是否会自动完成?
  • 它们在发出所有值后立即完成。但 switchMap 会一直监听主数据流,直到完成关闭整个序列。