途中でパイプを止めて

Dec 15 2020

私のAngularアプリには、401-Unauthorizedエラーをインターセプトし、アクセストークンの更新を試み、元のhttpリクエストを再度実行するトークン更新インターセプターがあります。

トークン更新エンドポイントも場合によっては失敗し、既知のエラーを返す可能性があります(私の場合は400invalid_grantエラーです)。

トークンを更新するインターセプターの部分:

 return this.httpClient
  .request('POST', "token", { observe: 'response' })
  .pipe(
    map(response => {
      // some logic when the token was refreshed successfully
    }),
    catchError(err => {
      this.routingService.navigateToLoginNoQuery();
      return throwError(err); // a 400 - invalid_grant error
    })
  );

これが発生すると、catchError演算子に到達し、2つのことを実行します。ログアウト(ログインページへのリダイレクトあり)とthrowError(error)を返します。このエラーは、400-Invalid_grantエラーです。

これにより、最初に更新トークンをトリガーした関数の一部のcatchError演算子に新しいエラーが到着します。

コンテキストのためだけに:私はcatchブロックにエラーを記録しますが、これらの種類のエラーは通常、ユーザーのトークンの有効期限が切れていることを意味するだけなので、ログに記録しないようにします。

私がやりたいのは、どういうわけかこの演算子チェーンを停止し、ログインページにリダイレクトすることです。

パイプを途中で停止し、外側のcatchErrorとパイプ内の次のオペレーターの両方に到達することを回避することは可能ですか?

回答

1 GuerricP Dec 14 2020 at 23:25

Observableを返すと、破壊されるコンポーネントにイベントやエラーが到達するのを防ぐことができます。

return this.httpClient
  .request('POST', "token", { observe: 'response' })
  .pipe(
    map(response => {
      // some logic when the token was refreshed successfully
    }),
    catchError(err => {
      this.routingService.navigateToLoginNoQuery();
      return EMPTY;
    })
  );
MishaBorisov Dec 14 2020 at 23:30

質問が正しいことを理解した場合は、takeUntil演算子が役立つかもしれません。例は次のようになります。

export class MyHttpInterceptor implements HttpInterceptor {
  anyError = new Subject();

  intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
      .pipe(
         takeUntil(this.anyError),
         catchError(err => {
             this.anyError.next();
             ...
         }
      )
  }
}