注入错误"提供程序解析错误:无法实例化循环依赖!"

its*_*ned 7 angular

我试图创建一个HttpInterceptor来为每个发生的http添加一些授权标头.我需要从名为AuthService的服务中获取标头.以下是代码:

拦截器:

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) { }
}
Run Code Online (Sandbox Code Playgroud)

AuthService:

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

@Injectable()
export class AuthService {
  constructor(private http: HttpClient) { }
}
Run Code Online (Sandbox Code Playgroud)

的AppModule:

providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AuthInterceptor,
    multi: true,
  }, AuthService]
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

错误:提供程序解析错误:无法实例化循环依赖项!InjectionToken_HTTP_INTERCEPTORS("[ERROR - >]"):在./AppModule@-1:-1中的NgModule AppModule中

我已经检查过以前的答案,但我不明白检测到循环依赖的位置.我要做的是在这里描述:https://angular.io/guide/http#setting-new-headers

ole*_*hko 20

看看这个GitHub讨论(问题#18224)

作为一种解决方法,您可以Injector手动使用并在intercept方法中注入相关服务:https://github.com/angular/angular/issues/18224#issuecomment-316957213

我决定不在构造函数中设置authService,而是进入拦截函数.

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();
    ...
}
Run Code Online (Sandbox Code Playgroud)

更新:

4.3.0不幸的是,在Angular之前,Injector手动内部intercept方法是不可能的:

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

所以还有一个解决方法使用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)
        })
}
Run Code Online (Sandbox Code Playgroud)


Veg*_*ega 6

从提供者列表中删除 AuthService,因为它已经导入到拦截器中,因此循环依赖。

  • AuthService 用于我的应用程序的许多部分,而且我到处都需要相同的实例。有什么选择吗? (3认同)
  • @KunalS 它看起来不是最好的,但我将它拆分,以便有两个相互独立的服务类。在第一个服务中,我拥有有关身份验证的所有变量,如令牌、用户名等。在第二个服务中,我只注册可观察对象来访问后端。这样,只有不访问身份验证变量的第二个服务才需要 http 导入和依赖项注入。在我的登录组件上,我导入了这两个服务。我从第二个服务发送请求。我收到响应并在第一个服务上设置变量。 (2认同)