如何在 intercept/arrow 函数中引用组件对象?

How to refer to component object within intercept/arrow function?

这是我的代码:

export class NetworkInterceptor implements HttpInterceptor {
  constructor(private router: Router, private ngZone: NgZone) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // ...

    return next.handle(request).pipe(
      finalize(() => {
        // ...
      }),
      tap({
        next(res) {},
        error(error) {
          if (error instanceof HttpErrorResponse) {
            if (error.status === 401) {
              this.ngZone.run(() => this.router.navigateByUrl('/account/signin'));
            }
          }
        },
        complete() {},
      })
    );
  }
}

但是不能用

this.ngZone.run(() => this.router.navigateByUrl('/account/signin'))

intercept 中,因为 this 不引用组件的对象。

正确的做法是什么?

尝试在拦截函数内为路由器实例声明一个局部变量。然后在代码中使用该变量。

intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // ...
    const interceptorRouter = this.router;
    return next.handle(request).pipe(
        finalize(() => {
            // ...
        }),
        tap({
            next(res) { },
            error(error) {
                if (error instanceof HttpErrorResponse) {
                    if (error.status === 401) {
                        this.ngZone.run(() => interceptorRouter.navigateByUrl('/account/signin'));
                    }
                }
            },
            complete() { }
        })
    );
}

这是我在过去的应用程序中使用的一种非常简单的方法,我不知道你是否觉得它足够优雅:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private router: Router, @Inject(WINDOW) private window: Window) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      catchError((error: HttpErrorResponse) => {
        if (error?.status === 401) {
          logout(this.window, this.router);
        }
        return throwError(error);
      })
    );
  }
}

如果与Window & Router相同,您可以注入NgZone

如果打算使用路由器服务导航到路由,则出现 401 错误时,您不需要使用 ngZone。 ngZone 是我们在从 angular 的 scope/zone.

外部引入 angular 事件时使用的服务

您需要以更简单的方式使用 catchError,您将通过以下方式为胜利做好准备:

export class NetworkInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    // ...
    return next.handle(req).pipe(
      catchError((err) => {
        if (err instanceof HttpErrorResponse && err.status === 401) {
          this.router.navigateByUrl('/account/signin');
        }
        return throwError(err);
      })
    );
  }
}

只需为您的点击负载使用箭头函数


tap({
  next: () => {...},
  error: () => {...},
  complete: () => {...},
})

EDIT 个人意见,但您应该使用 catchError 运算符,这似乎更适合您的情况。