1

我正在致力于使用TypeScript的Aurelia CLI项目和致力于对.NET Core/Web API后端进行HTTP调用的aurelia-fetch-client如何正确使用自定义Aurelia http-fetch-client拦截器的responseError?

服务器通过返回一个ApiError JSON结果作为API响应的主体,并且状态码在5xx范围内来标准化未处理的异常。

在客户端,我想使用拦截器执行客户端发布这些错误,但添加拦截器是以不希望的方式更改控制流。

main.ts相关配置:

function configureContainer(container: Container) { 
    const http = new HttpClient(); 
    http.configure((config: HttpClientConfiguration) => { 
     config.useStandardConfiguration() 
      .withBaseUrl("/api/") 
      .withInterceptor(new ApiErrorInterceptor(container.get(EventAggregator))); 
    }); 

    container.registerInstance(HttpClient, http); 
} 

这是拦截器:

import { autoinject } from "aurelia-framework"; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { Interceptor } from "aurelia-fetch-client"; 

@autoinject 
export class ApiErrorInterceptor implements Interceptor { 
    constructor(private readonly _aggregator: EventAggregator) { 
    } 

    responseError(error: any) { 
     // do something with the error    

     return error; 
    } 
} 

如果未添加自定义拦截器,则非OK响应记录为错误在Chrome中是这样的:

Unhandled rejection (<{}>, no stack trace) 

但是如果拦截器被加入,承诺不会再导致未处理的拒绝错误,并且调用代码继续,就好像承诺已经解决一样,这不是我们想要的,因为它引入了整个应用程序控制流程的巨大变化。

如何实现responseError()处理程序,以便控制流程与以前一样工作?这甚至是可能的,还是我误解了这个处理程序的目的?

我试着重新抛出返回的错误insteading,但是这不会针对Interceptor接口进行编译。例如,我应该在response()中这样做吗?

编辑:

这是我们最后使用,望着取出处和相关奥里利亚来源更详细经过。它仅在response()处理程序中处理基于服务器的错误,并在仅响应error()中处理基于客户端的连接错误。

import { autoinject } from "aurelia-framework"; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { Interceptor } from "aurelia-fetch-client"; 
import { TypedJSON } from "typedjson-npm"; 
import { EventNames } from "../model/EventNames"; 
import { ApiError } from "../model/ApiError"; 

@autoinject 
export class ApiErrorInterceptor implements Interceptor { 
    constructor(private readonly _aggregator: EventAggregator) { 
    } 

    async response(response: Response, request?: Request) { 
     if (!response.ok) { 
      // publish an error for the response 
      const apiError = await this.translateToApiError(response.clone()); 
      if (apiError) { 
       this._aggregator.publish(EventNames.apiError, apiError); 
      } 
     } 

     return response; 
    } 

    responseError(error: any) { 
     // publish errors resulting from connection failure, etc 
     if (error instanceof Error) { 
      const apiError = new ApiError(); 
      apiError.statusCode = 0; 
      apiError.isError = true; 
      apiError.message = error.message; 

      this._aggregator.publish(EventNames.apiError, apiError); 
     } 

     return error; 
    } 

    private async translateToApiError(response: Response): Promise<ApiError> { 
     let apiError: ApiError | undefined = undefined; 
     const text = await response.text(); 

     if (text) { 
      apiError = TypedJSON.parse(text, ApiError); 
     } 

     if (!apiError) { 
      apiError = this.getHttpError(response); 
     } 

     return apiError; 
    } 

    private getHttpError(response: Response): ApiError { 
     const apiError = new ApiError(); 
     apiError.isError = true; 
     apiError.statusCode = response.status; 
     apiError.message = "Unknown HTTP Error"; 

     switch (apiError.statusCode) { 
      case 400: 
       apiError.message = "Bad Request"; 
       break; 

      case 401: 
       apiError.message = "Unauthorized Access"; 
       break; 

      case 404: 
       apiError.message = "Not Found"; 
       break; 
     } 

     if (apiError.statusCode >= 500 && apiError.statusCode < 600) { 
      apiError.message = "Internal Server Error"; 
     } 

     return apiError; 
    } 
} 
+0

嗨,你看看获取源代码?据我所知,抓取,作为HTTP客户端永远不会拒绝承诺。它将始终调用响应,您必须检查状态码。我认为你正在做的方式(返回错误)是正确的,你只需要处理响应中的错误。 –

回答

0

使用代替return error;return Promise.reject(error);正在编制和使用你的代码预期工作。返回错误假定您解决了响应,并将您的返回值传递给已解析的代码路径,这就是您看到不希望的行为的原因。

0

responseError的错误参数是任何,所以请确保它是你认为它是。在我的情况下,我期待着失败的回应,但回到了一个被捕获的例外情况TypeError。这是我的拦截器:

responseError(response: any): Promise<Response> { 
    if (response instanceof Response) { 
     return response.json().then((serverError: ServerError) => { 

      // Do something with the error here. 

      return Promise.reject<Response>(serverError.error); 
     }); 
    } 
} 

我也有问题源于我的异常处理中间件在.NET Core应用程序中配置的方式。在我的情况下,UseDeveloperExceptionPage在提取客户端中导致CORS错误。这听起来不像是你的问题,但你可以将你的配置与我的here进行比较。