web-dev-qa-db-ja.com

Angular 5サービスを注入する際の5つのHTTPインターセプターエラー

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にサービスを注入することが技術的に可能であるようです。制限や欠落している可能性のある他のセットアップはありますか?

14
dev7

したがって、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();
    }
}

これはうまくいくようです。これが誰かを助けることを願っています。

6
dev7

2018年1月末に更新

Angular Teamは、この問題をAngular 5.2.3、2018年1月31日リリース)で解決しました。angularバージョンを更新すると、コンストラクタ

バグの修正

common:HttpInterceptorsにHttpClientの注入を許可(#19809)(ed2b717)、クローズ#18224

from Angular changelog

10
Gwidon

コンストラクターに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';
4

インターセプターと組み合わせた認証サービスの同じ設計で同様の問題が発生しました。

@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つのコンストラクターで行われ、インジェクターのシングルトンパターンを壊し、コールスタックから外れます。

2
Edward Liang

この問題については、Httpインターセプターで注入するサービスを、モジュールのHTTP_INTERCEPTORSとともにプロバイダーに追加する必要があることを確認してください。

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