【问题标题】:Angular Observable HttpInterceptor ForkJoin Not WorkingAngular Observable HttpInterceptor ForkJoin 不工作
【发布时间】:2020-10-02 21:19:42
【问题描述】:

我看到很多人提到这个问题,但没有找到任何解决方案。 我做了一个HttpInterceptor 将令牌添加到我的请求中。由于我使用 Firebase 进行身份验证,因此检索令牌需要一个 observable。一切正常,并且添加了令牌,但如果我将多个请求与 forkJoin 结合使用,它将不起作用。

HttpInterceptor

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.auth.idToken.pipe(
        mergeMap((token: any) => {
            if (token) {
                request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
            }
            return next.handle(request);
        })
    );
}

一些服务

forkJoin(
    this._dataService1.fetch(),
    this._dataService2.fetch(),
).subscribe(
    ([dataService1Data, dataService1Data]) => {
        alert("Completed");  // <-------- This line of code is never reached
    }
)

不幸的是,尽管我在网络选项卡中看到两个请求都成功完成,但从未到达代码中的上述行。有人可以给我一个解决方案吗? (上面的两个 fetch 方法都会触发一个 Http GET 请求。)

编辑

this._dataService1.fetch().subscribe(data => {
    console.log(data);
});
this._dataService2.fetch().subscribe(data => {
    console.log(data);
});

上面的代码工作得很好。正如我所提到的,它确实适用于个人请求,但不适用于 forkJoin

【问题讨论】:

    标签: angular httpclient angular-http-interceptors fork-join


    【解决方案1】:

    forkJoin 仅在 Observable 完成时发出。但是,您的 Observable 拦截器永远不会完成。将take(1) 运算符添加到您的拦截器:

    return this.auth.idToken.pipe(
            take(1),
            mergeMap((token: any) => {
                if (token) {
                    request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
                }
                return next.handle(request);
            })
        );
    

    【讨论】:

    • 我收到一条错误消息,提示“‘1’类型的参数不可分配给‘List‘”类型的参数
    • 您没有使用正确的take rxjs 运算符。检查你的导入,应该是:import {take} from 'rxjs/operators';
    • 非常感谢!!作品!我不小心输入了错误的运算符。您能否向我解释一下为什么我需要 take(1) 而它的 observable 永远不会完成?
    • 您的idToken 必须是一个永不结束的流Observable。所以mergeMap 操作员将发送一个请求token 的每个值 ==> 如果您从idToken 发出 10 个值,您可以发送相同的请求 10 次。你的基地Observable idToken 永远不会结束 ==> 拦截器永远不会结束。使用take(1)的意思是:等待token的第一个值,然后从基础Observable退订,这样拦截器Observable在收到第一个请求响应时就完成了。
    【解决方案2】:

    观察者需要完成forkJoin 才能发射。如果 observables 是流,你可以使用 RxJS combineLatest 并在 take(1) 中使用管道。试试下面的

    combineLatest(
      this._dataService1.fetch(),
      this._dataService2.fetch(),
    ).pipe(
      take(1)
    ).subscribe(
      ([dataService1Data, dataService1Data]) => {
        alert("Completed");  // <-------- This line of code is never reached
      }
    );
    

    【讨论】:

    • 非常感谢,它有效!运营商太多了,我什么都得不到。 take(1) 有什么作用?我怎么知道我的 observables 是否是流?
    • take() 操作员监听特定数量的通知并完成。所以take(1) 只听一个发射并完成。关于流,默认情况下可观察对象是流。一些实现只发出一个通知并完成,例如 Angular HttpClient observables。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 2021-03-02
    • 2022-01-20
    • 2021-03-27
    相关资源
    最近更新 更多