throwError(error) 现已弃用,但没有新的 Error(HttpErrorResponse)

nop*_*nop 83 rxjs typescript angular angular12

显然throwError(error)现在已被弃用。VS Code 的 IntelliSense 建议throwError(() => new Error('error')new Error(...)仅接受字符串。在不破坏我的情况下更换它的正确方法是什么HttpErrorHandlerService

\n

http-error.interceptor.ts

\n
import { Injectable } from '@angular/core';\nimport {\n  HttpEvent,\n  HttpInterceptor,\n  HttpHandler,\n  HttpRequest,\n  HttpErrorResponse,\n  HttpResponse,\n  HttpHeaders\n} from '@angular/common/http';\nimport { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';\n\nimport { HttpErrorHandlerService } from '@core/services';\n\n@Injectable()\nexport class HttpErrorInterceptor implements HttpInterceptor {\n  private readonly APP_XHR_TIMEOUT = 6000;\n\n  constructor(private errorHandlerService: HttpErrorHandlerService) {}\n\n  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n    return next.handle(this.performRequest(request)).pipe(\n      timeout(this.APP_XHR_TIMEOUT),\n      map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),\n      catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),\n      finalize(this.handleRequestCompleted.bind(this))\n    );\n  }\n\n  private performRequest(request: HttpRequest<any>): HttpRequest<any> {\n    let headers: HttpHeaders = request.headers;\n    //headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);\n    return request.clone({ headers });\n  }\n\n  private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {\n    if (event instanceof HttpResponse) {\n      event = event.clone({ body: event.body.response });\n    }\n    return event;\n  }\n\n  private processRequestError(\n    error: HttpErrorResponse,\n    request: HttpRequest<any>,\n    next: HttpHandler\n  ): Observable<HttpEvent<any>> {\n    console.log('http error response');\n\n    if ([401].includes(error.status)) {\n      return throwError(error);\n    }\n\n    this.errorHandlerService.handle(error);\n\n    return throwError(error);\n  }\n\n  private handleRequestCompleted(): void {\n    // console.log(`Request finished`);\n  }\n}\n\nimport { Injectable } from '@angular/core';\nimport { HttpErrorResponse } from '@angular/common/http';\n\nimport { MessageService } from 'primeng/api';\nimport { TimeoutError } from 'rxjs';\n\n/**\n * Shows a user-friendly error message when a HTTP request fails.\n */\n@Injectable({\n  providedIn: 'root'\n})\nexport class HttpErrorHandlerService {\n  constructor(private messageService: MessageService) {}\n\n  handle(error: Error | HttpErrorResponse) {\n    if (error instanceof TimeoutError) {\n      return this.openDialog('error', `\xd0\x9d\xd1\x8f\xd0\xbc\xd0\xb0 \xd0\xb2\xd1\x80\xd1\x8a\xd0\xb7\xd0\xba\xd0\xb0 \xd0\xb4\xd0\xbe \xd1\x81\xd1\x8a\xd1\x80\xd0\xb2\xd1\x8a\xd1\x80\xd0\xb0.`);\n    }\n\n    if (error instanceof HttpErrorResponse && error.error && error.error.message) {\n      return this.openDialog('error', error.error.message);\n    }\n\n    if (error instanceof Error) {\n      switch (error.message) {\n        default:\n          return this.openDialog('error', `An unknown error occurred`);\n      }\n    }\n\n    // Generic HTTP errors\n    switch (error.status) {\n      case 400:\n        switch (error.error) {\n          case 'invalid_username_or_password':\n            return this.openDialog('error', '\xd0\x9d\xd0\xb5\xd0\xb2\xd0\xb0\xd0\xbb\xd0\xb8\xd0\xb4\xd0\xbd\xd0\xbe \xd0\xbf\xd0\xbe\xd1\x82\xd1\x80\xd0\xb5\xd0\xb1\xd0\xb8\xd1\x82\xd0\xb5\xd0\xbb\xd1\x81\xd0\xba\xd0\xbe \xd0\xb8\xd0\xbc\xd0\xb5 \xd0\xb8\xd0\xbb\xd0\xb8 \xd0\xbf\xd0\xb0\xd1\x80\xd0\xbe\xd0\xbb\xd0\xb0');\n          default:\n            return this.openDialog('error', 'Bad request');\n        }\n\n      case 401:\n        return this.openDialog('error', '\xd0\xa9\xd0\xb5 \xd1\x82\xd1\x80\xd1\x8f\xd0\xb1\xd0\xb2\xd0\xb0 \xd0\xb4\xd0\xb0 \xd1\x81\xd0\xb5 \xd0\xbb\xd0\xbe\xd0\xb3\xd0\xbd\xd0\xb5\xd1\x82\xd0\xb5 \xd0\xbe\xd1\x82\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe');\n\n      case 403:\n        return this.openDialog('error', `You don't have the required permissions`);\n\n      case 404:\n        return this.openDialog('error', 'Resource not found');\n\n      case 422:\n        return this.openDialog('error', 'Invalid data provided');\n\n      case 500:\n      case 501:\n      case 502:\n      case 503:\n        return this.openDialog('error', 'An internal server error occurred');\n\n      case -1:\n        return this.openDialog(\n          'error',\n          'You appear to be offline. Please check your internet connection and try again.'\n        );\n\n      case 0:\n        return this.openDialog('error', `CORS issue?`);\n\n      default:\n        return this.openDialog('error', `An unknown error occurred`);\n    }\n  }\n\n  private openDialog(severity: string, message: string) {\n    if (message?.trim()) {\n      this.messageService.add({\n        key: 'interceptor',\n        severity: severity,\n        summary: '\xd0\x98\xd0\xbd\xd1\x84\xd0\xbe\xd1\x80\xd0\xbc\xd0\xb0\xd1\x86\xd0\xb8\xd1\x8f',\n        detail: message,\n        life: 3000\n      });\n    }\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

auth.interceptor.ts

\n
import { Injectable } from '@angular/core';\nimport {\n  HttpRequest,\n  HttpHandler,\n  HttpEvent,\n  HttpInterceptor,\n  HttpErrorResponse\n} from '@angular/common/http';\nimport {\n  BehaviorSubject,\n  catchError,\n  EMPTY,\n  filter,\n  finalize,\n  Observable,\n  switchMap,\n  take,\n  throwError\n} from 'rxjs';\n\nimport { AuthService } from '@core/services';\nimport { AuthResponse } from '@core/types';\n\n@Injectable()\nexport class AuthInterceptor implements HttpInterceptor {\n  private refreshTokenInProgress: boolean;\n  private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);\n\n  constructor(private authService: AuthService) {}\n\n  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n    return next\n      .handle(this.performRequest(request))\n      .pipe(\n        catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))\n      );\n  }\n\n  private performRequest(request: HttpRequest<any>): HttpRequest<any> {\n    const accessToken = this.authService.getAccessToken();\n\n    let headers = request.headers;\n    if (accessToken) {\n      headers = headers.set('Authorization', `Bearer ${accessToken}`);\n    }\n\n    return request.clone({ headers });\n  }\n\n  private processRequestError(\n    error: HttpErrorResponse,\n    request: HttpRequest<any>,\n    next: HttpHandler\n  ): Observable<HttpEvent<any>> {\n    console.log('auth interceptor called');\n\n    if (\n      error instanceof HttpErrorResponse &&\n      error.status === 401 &&\n      this.authService.isSignedIn()\n    ) {\n      return this.refreshToken(request, next);\n    }\n\n    return throwError(error);\n  }\n\n  private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n    console.log('refresh token in auth.interceptor called');\n\n    // in case the page consists of more than one requests\n    if (!this.refreshTokenInProgress) {\n      this.refreshToken$.next(null);\n      this.refreshTokenInProgress = true;\n\n      return this.authService.refreshToken().pipe(\n        switchMap((response) => {\n          if (response) {\n            this.refreshToken$.next(response);\n            return next.handle(this.performRequest(request));\n          }\n\n          this.authService.signOut();\n          return throwError(() => new Error("RefreshTokenFailed"));\n        }),\n        catchError((error) => {\n          this.authService.signOut();\n          return throwError(error);\n        }),\n        finalize(() => (this.refreshTokenInProgress = false))\n      );\n    } else {\n      // wait while getting new token\n      return this.refreshToken$.pipe(\n        filter((result) => result !== null),\n        take(1),\n        switchMap(() => next.handle(this.performRequest(request)))\n      );\n    }\n  }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

Deb*_*ahK 204

而不是这个:

    catchError((error) => {
      this.authService.signOut();
      return throwError(error);
    }),
Run Code Online (Sandbox Code Playgroud)

你可以试试这个:

    catchError((error) => {
      this.authService.signOut();
      return throwError(() => error);
    }),
Run Code Online (Sandbox Code Playgroud)

我无法彻底测试它,但一个简单的尝试似乎有效。

这是我的简单测试(使用 RxJS v7.2):

服务

  getProducts(): Observable<IProduct[]> {
    return this.http.get<IProduct[]>(this.productUrl)
      .pipe(
        tap(data => console.log('All: ', JSON.stringify(data))),
        catchError(this.handleError)
      );
  }

  private handleError(err: HttpErrorResponse): Observable<never> {
    // just a test ... more could would go here
    return throwError(() => err);
  }
Run Code Online (Sandbox Code Playgroud)

请注意,err这里的类型是HttpErrorResponse

成分

  ngOnInit(): void {
    this.sub = this.productService.getProducts().subscribe({
      next: products => {
        this.products = products;
        this.filteredProducts = this.products;
      },
      error: err => this.errorMessage = err.message
    });
  }
Run Code Online (Sandbox Code Playgroud)

在这里,我能够message从错误响应中检索该属性并将其显示在我的 UI 中。

让我知道这是否适合您。


Ali*_*avi 10

只需使用:

return new Error(message);
Run Code Online (Sandbox Code Playgroud)

不必要的使用

return throwError(() => new Error(message));
Run Code Online (Sandbox Code Playgroud)

请参阅此处的示例

  • @DeborahK,因为作者询问如何保留非字符串错误值,而“new Error()”仅支持“字符串”。 (5认同)
  • 不知道为什么这被否决了(我刚刚投票赞成),因为这也是一个很好的答案。如果您点击上面的链接,甚至 RxJS 文档也建议使用“new Error()”语法。 (3认同)