2017-08-12 10 views
5

Próbowałem utworzyć HttpInterceptor, aby dodać nagłówki autoryzacji do każdego http, który się dzieje. Potrzebuję pobrać nagłówki z usługi o nazwie AuthService. Oto poniżej kod:Błąd wtryskiwacza "Błąd analizy dostawcy: nie można utworzyć wystąpienia zależności cyklicznej!"

Interceptor:

import { Injectable } from '@angular/core'; 
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; 
import { AuthService } from './auth.service'; 

@Injectable() 
export class AuthInterceptor implements HttpInterceptor { 
    constructor(private auth: AuthService) { } 
} 

AuthService:

import { HttpClient } from '@angular/common/http'; 
import { Injectable } from '@angular/core'; 

@Injectable() 
export class AuthService { 
    constructor(private http: HttpClient) { } 
} 

AppModule:

providers: [{ 
    provide: HTTP_INTERCEPTORS, 
    useClass: AuthInterceptor, 
    multi: true, 
    }, AuthService] 

I pojawia się następujący błąd:

Error: Provider parse errors: Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./[email protected]:-1

Sprawdziłem już poprzednie odpowiedzi, ale nie rozumiem, gdzie wykryto cykliczną zależność. Co próbuję zrobić jest opisany tutaj: https://angular.io/guide/http#setting-new-headers

Odpowiedz

7

Spójrz na to GitHub Discussion (Issue #18224)

jako obejście można użyć Injector ręcznie i wstrzyknąć odpowiednią usługę wewnątrz intercept metody: https://github.com/angular/angular/issues/18224#issuecomment-316957213

I resolved simply not setting authService in constructor but getting in the intercept function.

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 
    // Get the auth header from the service. 
    const auth = this.inj.get(AuthenticationService); 
    const authToken = auth.getAuthorizationToken(); 
    ... 
} 

UPDATE:

Przed kątowa 4.3.0 un Na szczęście jest to niemożliwe do zastosowania Injector ręcznie wewnątrz intercept metody:

ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceeded

Więc jest jeszcze jedna obejście użyciu rxjs:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 
    return Observable.create((observer: any) => { 
     setTimeout(() => { 
      const authService = this.injector.get(AuthenticationService) 
      observer.next(authService.getAuthorizationHeader()) 
      observer.complete() 
     }) 
    }) 
     .mergeMap((Authorization: string) => { 
      let authReq = req 

      if (Authorization) { 
       authReq = req.clone({ 
        setHeaders: { 
         Authorization 
        } 
       }) 
      } 

      return next.handle(authReq) 
     }) 
} 
+0

Bardzo ładna i czysta odpowiedź, wielkie dzięki! :) – dave0688

2

Usuń AuthService z listy dostawców, ponieważ jest importowany w Interceptor już w ten sposób zależność cykliczna.

+2

AuthService jest stosowany w wielu częściach mojego wniosku i muszę tę samą instancję wszędzie. Jakaś opcja? – itsundefined

+0

Myślę, że naprawiłem problem, ale wygląda na głupio ... Rozdzieliłem authService na dwie części. W jednym pliku mam wszystkie zmienne, a po drugiej wszystkie żądania HTTP. W ten sposób wymagam tylko zmiennych na moim Interceptorze, eliminując cykliczną zależność. Czy to jest anty-wzór, czy powinienem go zatrzymać? W każdym razie dziękuję za poświęcony czas. – itsundefined

+0

@itsUndefined W jaki sposób podzieliłeś swoją klasę usług na dwie? jest to jak dwie oddzielne klasy wywodzące się z podstawowej klasy usług? –

Powiązane problemy