Угловой HttpInterceptor не работает с forkJoin - PullRequest
0 голосов
/ 31 мая 2018

У меня есть Служба для получения токена от типа 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

Это будет работать, только если я добавлю дубль (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 голосов
/ 21 августа 2018

Я решил проблему, преобразовав токен из Observable в строку.и я решил проблему, сделав это.

0 голосов
/ 22 августа 2018

Насколько я понимаю, в перехватчике, если вы используете токен как Observable и switchMap, вы можете в конечном итоге один запрос отменить другой.

Ваш конкретный пример превратится в: (getUsers fires -> interceptsдобавляет токены и срабатывает getPosts -> перехват добавляет токен) -> switchMap (отменить предыдущий перехваченный запрос) -> фактически срабатывает только 1 запрос.

forkJoin требует, чтобы обе наблюдаемые были завершены для запуска, поэтому ваша ситуацияесли один получает ответ от сервера, другой хранит молчание.

Вы можете использовать mergeMap вместо switchMap (который не отменяет запрос), однако лучшим решением будет использование switchMap перед вызовом функции services.

Кроме того, было бы разумно сделать токен в виде строки, а не наблюдать, так как он редко изменяется во время сеанса, и вы можете использовать set-get to localStorage, чтобы убедиться, что он актуален.

Надеюсь, это поможет.

0 голосов
/ 31 мая 2018

Попробуйте использовать следующую Наблюдаемую конфигурацию, добавив 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);

} );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...