Angular HttpInterceptor not working with forkJoin

99封情书 提交于 2019-12-24 06:43:55

问题


I have Service to get the token from type Observable and HttpInterceptor to use it to inject the token in every http request. The thing is it works fine with a single request but if i used forkJoin i will not get any response back.

the interceptor code

import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { AppService } from './app.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(
    private service: AppService
  ) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.service.token$.pipe(
      map((token: string) => {
        if (token) {
          const headers = req.headers.set('Authorization', `Bearer ${token}`);
          console.log(`Request for url ${req.url}`);
          req = req.clone({
            headers: headers
          });
        }
        return req;
      }
      ),
      switchMap(newReq => next.handle(newReq))
    )
  }
}

and simple two requests like those

  getUsers() {
    return this.http.get<any[]>(`https://jsonplaceholder.typicode.com/users`);
  }

  getPosts() {
    return this.http.get<any[]>(`https://jsonplaceholder.typicode.com/posts`);
  }

And in the component

// Single One will work
 this.appService.getPosts().subscribe(res => console.warn(res));

// Will not work
    forkJoin([this.appService.getPosts(), this.appService.getUsers()])
      .subscribe(([posts, users]) => {
        console.log(posts, users);
      });

I re-produced the error on example you can check it https://stackblitz.com/edit/angular-kpxvej

It will work only if i add take(1) in the interceptor but then it will not be the thing i want because i got a new value for the token will not use it.

and in other case if token was just a string will work like that

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.service.getToken();
    const headers = req.headers.set('Authorization', `Bearer ${token}`);
    console.log(`Request for url ${req.url}`);
    req = req.clone({
      headers: headers
    });
    return next.handle(req);
  }

回答1:


From my understanding, in the interceptor if you make use of token as Observable and switchMap, you may end up one request cancel the other.

Your specific example would turn into: (getUsers fires -> intercepts adds token & getPosts fires -> intercept adds token) -> switchMap (cancel the previous intercepted request) -> only 1 request actually fires.

forkJoin requires both observables to be completed in order to fire, so your situation is one gets server response, the other remains silent.

You can use mergeMap instead of switchMap (which won't cancel the request), however the best solution would be using switchMap prior to calling the services function.

Also, it would be reasonable to make token as a string rather than observable as it rarely changes during a session, and you can make use of set-get to localStorage to make sure it's up-to-date.

Hope it helps.




回答2:


Try by using the following Observable configuration by adding the forkjoin as observable.

service.ts

getUsers(): Observable<any[]> {

        return this.http.get(`https://jsonplaceholder.typicode.com/users`)
        .map(res => { 
            return res;
          });
    }

getPosts(): Observable<any[]> {            
            return this.http.get(`https://jsonplaceholder.typicode.com/posts`);
            .map(res => { 
                return res;
              });
        }

getForkJoin(): Observable<any>{
        return forkJoin(
            this.getUsers(),
            this.getPosts()           
        );
    }

Component.ts

this.appService.getForkJoin().subscribe(([users,posts]) =>{

console.log(users);
console.log(posts);

} );



回答3:


I solved the problem by converting the token from Observable to be just a string. and i solved the problem by doing that.



来源:https://stackoverflow.com/questions/50614121/angular-httpinterceptor-not-working-with-forkjoin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!