angular 5+。でカスタムHttpInterceptorsを使用すると、次の奇妙な依存性注入動作を受け取ります。
次の簡略化されたコードは正常に機能します。
_ export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.auth.getToken();
return next.handle(req);
}
}
export class AuthService {
token: string;
constructor() {
console.log('AuthService.constructor');
}
}
_
しかしながら....
AuthService
がそれ自体に対して1つ以上の依存関係を持っている場合.
_ export class AuthService {
token: string;
constructor(private api: APIService) {
console.log('AuthService.constructor');
}
}
_
アンギュラーは、次のエラーを受け取るまで、AuthService
の新しいインスタンスを繰り返し作成しようとしています。
ログは_AuthService.constructor
_メッセージを最大400回表示しています
そして
Cannot instantiate cyclic dependency! HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule
そして
app.component.html:44エラーRangeError:最大呼び出しスタックサイズを超えました
次に、Injectorクラスを使用してサービスを注入しようとしました-
_ export class AuthService {
token: string;
api: APIService;
constructor(private injector: Injector) {
this.api = this.injector.get(APIService);
console.log('AuthService.constructor');
}
}
_
ただし、同じエラー(最大呼び出しスタックサイズ)が発生します。
APIService
は、そのコンストラクターにHttpClient
を注入するだけの単純なサービスです。
_@Injectable()
export class APIService {
constructor(private http: HttpClient) {}
}
_
最後に、AuthService
を使用してInjector
をインターセプターに挿入すると、エラーは消えますが、AuthServiceは200回以上インスタンス化されます。
_export class AuthInterceptor implements HttpInterceptor {
auth: AuthService;
constructor(private injector: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.auth = this.auth || this.injector.get(AuthService);
const token = this.auth.getToken();
return next.handle(req);
}
}
_
公式ドキュメントと他の例を見ると、Http Interceptorにサービスを注入することが技術的に可能であるようです。制限や欠落している可能性のある他のセットアップはありますか?
したがって、Http Interceptorに注入するサービスがHttpClient
に依存している場合、これは循環依存につながります。
私のAuthService
はすべての異なるロジック(ログイン/ログアウト、ユーザーのルーティング、トークンの保存/読み込み、API呼び出しの作成)であったため、インターセプターに必要な部分を独自のサービス(ユーザーのみ)に分離しました資格情報とトークン)を取得し、インターセプターに正常に挿入します。
export class AuthInterceptor implements HttpInterceptor {
constructor(private credentials: CredentialsService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.credentials.getToken();
const api_key = this.credentials.getApiKey();
}
}
export class CredentialsService {
token: string;
user: IUser;
constructor(private http: HttpClient) {
this.loadCredentialsFromStorage();
}
}
これはうまくいくようです。これが誰かを助けることを願っています。
Angular Teamは、この問題をAngular 5.2.3、2018年1月31日リリース)で解決しました。angularバージョンを更新すると、コンストラクタ
バグの修正
common:HttpInterceptorsにHttpClientの注入を許可(#19809)(ed2b717)、クローズ#18224
コンストラクターにInjector
を追加し、インジェクターを介してAuthService
を注入する必要があります
export class AuthInterceptor implements HttpInterceptor {
constructor(private inj: Injector) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const auth = this.inj.get(AuthService);
const token = this.auth.getToken();
return next.handle(req);
}
}
インポートを忘れないでください
import {Injector} from '@angular/core';
インターセプターと組み合わせた認証サービスの同じ設計で同様の問題が発生しました。
@Injectable() AuthInterceptorService {
constructor (authApi: AuthApiService) {}
handle () {...do the job}
}
@Injectable() AuthApiService {
constructor () {
// ...do some setup with a request, such as to get current session
// that leads to an indirect circular between 2 constructors.
}
}
私の場合、原因は認証サービスのコンストラクターでhttpリクエストを開始しようとしていることです。その時点で、インジェクターは認証サービスのインスタンスの登録を完了していないように見えますが、HTTPクライアントは新しいリクエストをキャプチャし、インターセプターを再びインスタンス化しようとしました。
この再帰呼び出しは2つのコンストラクターで行われ、インジェクターのシングルトンパターンを壊し、コールスタックから外れます。
この問題については、Httpインターセプターで注入するサービスを、モジュールのHTTP_INTERCEPTORSとともにプロバイダーに追加する必要があることを確認してください。
providers: [ AuthService,
{
provide: HTTP_INTERCEPTORS,
useClass: HttpConfigInterceptor,
multi: true
}
]