HTTP请求

关于 HttpClient

Angular具有很棒的 HttpClient 与后端服务进行通信. 它位于顶层,是XMLHttpRequest Web API的封装. 同时也是Angular建议用于任何HTTP请求的代理,在你的ABP项目中使用 HttpClient 是最佳做法.

但是 HttpClient 将错误处理留给调用方,换句话说HTTP错误是通过手动处理的,通过挂接到返回的 Observable 的观察者中来处理.

  1. getConfig() {
  2. this.http.get(this.configUrl).subscribe(
  3. config => this.updateConfig(config),
  4. error => {
  5. // Handle error here
  6. },
  7. );
  8. }

上面的代码尽管清晰灵活,但即使将错误处理委派给Store或任何其他注入. 以这种方式处理错误也是重复性的工作.

HttpInterceptor 能够捕获 HttpErrorResponse 并可用于集中的错误处理. 然而,在必须放置错误处理程序(也就是拦截器)的情况下,需要额外的工作以及对Angular内部机制的理解. 检查这个issue了解详情.

RestService

ABP核心模块有用于HTTP请求的实用程序服务: RestService. 除非另有明确配置,否则它将捕获HTTP错误并调度 RestOccurError 操作, 然后由 ThemeSharedModule 引入的 ErrorHandler 捕获此操作. 你应该已经在应用程序中导入了此模块,在使用 RestService 时,默认情况下将自动处理所有HTTP错误.

RestService 入门

为了使用 RestService, 你必须将它注入到你的类中.

  1. import { RestService } from '@abp/ng.core';
  2. @Injectable({
  3. /* class metadata here */
  4. })
  5. class DemoService {
  6. constructor(private rest: RestService) {}
  7. }

你不必在模块或组件/指令级别提供 estService,因为它已经在根中中提供了.

如何使用RestService发出请求

你可以使用 RestServicerequest 方法来处理HTTP请求. 示例:

  1. getFoo(id: number) {
  2. const request: Rest.Request<null> = {
  3. method: 'GET',
  4. url: '/api/some/path/to/foo/' + id,
  5. };
  6. return this.rest.request<null, FooResponse>(request);
  7. }

request 方法始终返回 Observable<T>. 无论何时使用 getFoo 方法,都可以执行以下操作:

  1. doSomethingWithFoo(id: number) {
  2. this.demoService.getFoo(id).subscribe(
  3. foo => {
  4. // Do something with foo.
  5. }
  6. )
  7. }

你不必担心关于取消订阅. RestService 在内部使用 HttpClient,因此它返回的每个可观察对象都是有限的可观察对象,成功或出错后将自动关闭订阅.

如你所见,request 方法获取一个具有 Rest.Reques<T> 类型的请求选项对象. 此泛型类型需要请求主体的接口. 当没有正文时,例如在 GETDELETE 请求中,你可以传递 null. 示例:

  1. postFoo(body: Foo) {
  2. const request: Rest.Request<Foo> = {
  3. method: 'POST',
  4. url: '/api/some/path/to/foo',
  5. body
  6. };
  7. return this.rest.request<Foo, FooResponse>(request);
  8. }

你可以在此处检查完整的 Rest.Request<T> 类型,与Angular中的HttpRequest类相比只有很少的改动.

如何禁用RestService的默认错误处理程序

默认 request 方法始终处理错误. 让我们看看如何改变这种行为并由自己处理错误:

  1. deleteFoo(id: number) {
  2. const request: Rest.Request<null> = {
  3. method: 'DELETE',
  4. url: '/api/some/path/to/foo/' + id,
  5. };
  6. return this.rest.request<null, void>(request, { skipHandleError: true });
  7. }

skipHandleError 配置选项设置为 true 时,禁用错误处理程序,并返回 observable 引发错误,你可以在订阅中捕获该错误.

  1. removeFooFromList(id: number) {
  2. this.demoService.deleteFoo(id).subscribe(
  3. foo => {
  4. // Do something with foo.
  5. },
  6. error => {
  7. // Do something with error.
  8. }
  9. )
  10. }

如何从应用程序配置获取特定的API端点

request 方法接收到的另一个配置选项是 apiName (在v2.4中可用),它用于从应用程序配置获取特定的模块端点.

  1. putFoo(body: Foo, id: string) {
  2. const request: Rest.Request<Foo> = {
  3. method: 'PUT',
  4. url: '/' + id,
  5. body
  6. };
  7. return this.rest.request<Foo, void>(request, {apiName: 'foo'});
  8. }

上面的putFoo将请求 https://localhost:44305/api/some/path/to/foo/{id} 当环境变量如下:

  1. // environment.ts
  2. export const environment = {
  3. apis: {
  4. default: {
  5. url: 'https://localhost:44305',
  6. },
  7. foo: {
  8. url: 'https://localhost:44305/api/some/path/to/foo',
  9. },
  10. },
  11. /* rest of the environment variables here */
  12. }

如何观察响应对象或HTTP事件而不是正文

RestService 假定你通常对响应的正文感兴趣,默认情况下将 observe 属性设置为 body. 但是有时你可能对其他内容(例如自定义标头)非常感兴趣. 为此, request 方法在 config 对象中接收 watch 属性.

  1. getSomeCustomHeaderValue() {
  2. const request: Rest.Request<null> = {
  3. method: 'GET',
  4. url: '/api/some/path/that/sends/some-custom-header',
  5. };
  6. return this.rest.request<null, HttpResponse<any>>(
  7. request,
  8. {observe: Rest.Observe.Response},
  9. ).pipe(
  10. map(response => response.headers.get('Some-Custom-Header'))
  11. );
  12. }

你可以在此处找到 Rest.Observe 枚举.

下一步是什么?