Angular HttpInterceptor无法使用forkJoin

时间:2018-05-30 22:22:54

标签: javascript angular typescript rxjs angular6

我有Service从Observable类型和HttpInterceptor获取令牌,以使用它在每个http请求中注入令牌。 事情是单个请求它工作正常但如果我使用forkJoin我将不会得到任何回复。

拦截器代码

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))
    )
  }
}

和简单的两个请求,如

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

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

在组件中

// 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);
      });

我重新制作了错误,例如你可以查看它 https://stackblitz.com/edit/angular-kpxvej

只有当我在拦截器中添加take(1)但它不会是我想要的东西时它才会起作用,因为我得到了一个新的代币值将不会使用它。

在其他情况下,如果令牌只是一个字符串将起作用 像那样

  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);
  }

3 个答案:

答案 0 :(得分:1)

据我所知,在拦截器中,如果您将令牌用作Observable和switchMap,则可能会导致一个请求取消另一个请求。

您的特定示例将变成:(getUsers触发->拦截添加令牌,getPosts触发->拦截添加令牌)-> switchMap(取消先前被拦截的请求)->实际上只有1个请求触发。

forkJoin要求完成两个可观察对象才能触发,因此您的情况是一个得到服务器响应,另一个保持沉默。

您可以使用mergeMap代替switchMap(这不会取消请求),但是最好的解决方案是在调用services函数之前使用switchMap。

此外,将令牌作为字符串而不是可观察的是合理的,因为它在会话期间很少更改,并且您可以使用set-get到localStorage来确保它是最新的。

希望有帮助。

答案 1 :(得分:0)

通过将forkjoin添加为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);

} );

答案 2 :(得分:0)

我通过将Observable的令牌转换成字符串来解决了这个问题。而我通过这样做解决了这个问题。