likes
comments
collection
share

Angular的HttpClient深入分析

作者站长头像
站长
· 阅读数 62

HttpClient执行http请求。该服务作为可注入类提供,带有执行 HTTP 请求的方法。每个请求方法都有多个签名,并且返回类型会根据所调用的签名(主要的值是 observe 和 responseType)而有所不同。

方法

/**构建HttpRequest参数**/
new HttpRequest(
    method: string, 
    url: string,
    body?:any, //相当于post参数
    third?: T | 
    {   headers?: HttpHeaders; 
        reportProgress?: boolean; 
        params?: HttpParams; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; 
        withCredentials?: boolean; 
    }, 
    fourth?: 
    {   headers?: HttpHeaders; 
        reportProgress?: boolean; 
        params?: HttpParams; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; 
        withCredentials?: boolean;
    }
);

/**HttpClient.request的参数**/
request(
    first: string | HttpRequest<any>, 
    url?: string, 
    options: { 
        body?: any; 
        headers?: HttpHeaders | { [header: string]: string | string[]; }; 
        observe?: HttpObserve; 
        params?: HttpParams | { [param: string]: string | string[]; }; 
        reportProgress?: boolean; 
        responseType?: "arraybuffer" | ... 2 more ... | "json"; withCredentials?: boolean; 
    } = {}): Observable<any> //返回值

/**HttpClient.get的参数**/
get(
    url: string, 
    options: { 
        headers?: HttpHeaders | { [header: string]: string | string[]; };
        observe?: HttpObserve; 
        params?: HttpParams | { [param: string]: string | string[]; }; 
        reportProgress?: boolean; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; withCredentials?: boolean; 
    } = {}): Observable<any>

/**HttpClient.delete的参数**/
delete(
    url: string, 
    options: { 
        headers?: HttpHeaders | { [header: string]: string | string[]; }; 
        observe?: HttpObserve; 
        params?: HttpParams | { [param: string]: string | string[]; }; 
        reportProgress?: boolean; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; withCredentials?: boolean; 
    } = {}): Observable<any> 

/**HttpClient.post的参数**/
post(
    url: string,
    body: any, 
    options: { 
        headers?: HttpHeaders | { [header: string]: string | string[]; }; 
        observe?: HttpObserve;
        params?: HttpParams | { [param: string]: string | string[]; }; 
        reportProgress?: boolean; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; 
        withCredentials?: boolean; 
    } = {}): Observable<any>

/**HttpClient.get的参数**/
put(
    url: string, 
    body: any, 
    options: { 
        headers?: HttpHeaders | { [header: string]: string | string[]; }; 
        observe?: HttpObserve; 
        params?: HttpParams | { [param: string]: string | string[]; }; 
        reportProgress?: boolean; 
        responseType?: "arraybuffer" | "blob" | "text" | "json"; withCredentials?: boolean; 
    } = {}): Observable<any>

//请求超时

 this.http.get('http://api.geonames.org/postalCodeSearchJSON'
 {search:params}) 
 .retryWhen(error => error.delay(500))
 .timeout(2000new Error('delay exceeded')) // <- 超时
 .map(res => res.json()。postalCodes);

参数说明

header

选项可用于设置请求头信息,可以帮助控制请求或处理响应数据的方式。

以下是 HttpClient 的 headers 选项示例说明:

  1. Content-Type

设置请求体的 MIME 类型,用于说明请求体的数据格式,例如 JSON 格式。

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
this.http.post(URL, body, httpOptions).subscribe(data => {
  console.log(data);
});
  1. Accept

设置响应体允许的 MIME 类型,用于告知服务器请求方能够处理的数据格式。

const httpOptions = {
  headers: new HttpHeaders({ 'Accept': 'application/json' })
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. Authorization

设置请求头的 token 或 JWT 字符串,用于验证身份。

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QifQ.O7lCStt09iW7Yz3MV9biEZZ6OkmiEnkGGTJw0d2mKpM';
const httpOptions = {
  headers: new HttpHeaders({ 'Authorization': `Bearer ${token}` })
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. Cache-Control

设置请求或响应的缓存控制策略。

const httpOptions = {
  headers: new HttpHeaders({ 'Cache-Control': 'no-cache' })
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});

除以上常见的请求头信息外,您也可以自行设置其他的请求头字段。需要注意的是,某些请求头字段可能需要特定的权限或设置才能正常工作。

context

HttpClient 的 context 选项实际上是 HttpClient 的扩展选项。可以用于传递从应用程序的各个部分收集到的上下文信息,这些信息可以帮助识别请求的来源或跟踪请求的执行情况。

以下是 HttpClient 的 context 选项示例说明:

  1. context

此选项允许您在应用程序的许多部分之间传递多个上下文值。为此,您可以定义输入类型为 HttpContext 的对象。例如:

import { HttpClient, HttpContext } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor(private http: HttpClient) {}

  sendRequest(url: string) {
    const context = new HttpContext().set(PERFORMANCE_MARK, 'foo');
    const options = { context }; // 将上下文传递给HttpClient的options选项
    return this.http.get(url, options);
  }
}
  1. ngContextToken

ngContextToken是一个特定于 Angular 的上下文令牌,可以传递给 HttpClient 的 context 选项以定义与 Angular 环境相关的信息。

import { HttpClient, ngContextToken } from '@angular/common/http';
import { ErrorHandler, Injectable, NgZone } from '@angular/core';

@Injectable()
export class MyErrorHandler implements ErrorHandler {
  constructor(private zone: NgZone, private http: HttpClient) {}

  handleError(error: any): void {
    const context = { info: error.message, zone: this.zone };
    const options = { context: new Map([[ngContextToken, context]]) };
    this.http.post('/api/error', { error }, options)
      .subscribe(() => { }, error => console.error(error));
  }
}

以上是 HttpClient 的 context 选项的示例说明,只要您定义 HttpClient 的 扩展选项 对象,添加您需要传递的上下文信息,就可以很容易地使用这个特性。

observe

选项有三个值:

  1. 'body': 仅请求响应体部分

通过传递该参数,您将只获得 Http 响应数据的主体部分。此选项适用于处理不需要或不关心进度情况的情形。

const httpOptions = { observe: 'body' };
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data); // 只获得响应体
});
  1. 'response': 整个请求响应

通过传递该参数,您将获得完整的 Http 响应数据,包括状态码、头部信息和响应主体。此选项适用于需要完整数据或处理请求进度的情形。

const httpOptions = { observe: 'response' };
this.http.get(URL, httpOptions).subscribe((response) => {
  console.log(response.status); // 显示状态码
  console.log(response.headers); // 显示头部信息
  console.log(response.body); // 显示响应主体
})
  1. 'events': 获得请求进度事件流

通过传递该参数,您将获得一个带有 Http 请求进度事件的 Observable 对象。此选项适用于需要监视请求进度的情形。

const httpOptions = { observe: 'events' };
this.http.get(URL, httpOptions).subscribe((event) => {
  if (event.type == HttpEventType.DownloadProgress) {
    console.log(`Received download progress: ${event.loaded} bytes of ${event.total}`)
  } else if (event.type == HttpEventType.Response) {
    console.log('Received full response: ', event.body)
  }
})

请注意,这些选项可以与 responseType 选项结合使用,以设置响应数据的类型。例如,将 'responseType' 设置为 'blob' 可以让您从响应中获取二进制数据。

params

HttpClient 的 params 选项用于设置查询字符串参数,可用于向 API 发送有关资源请求所需的参数。这些参数将作为 HTTP 请求的一部分传递,并在服务器端解析和使用。

以下是 HttpClient 的 params 选项示例说明:

  1. 传递简单字符串参数

可以通过设置 params 选项来传递简单的查询字符串参数。例如,以下请求将在 URL 上添加名为 'q' 的查询参数。

const httpOptions = {
  params: { q: 'search' }
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. 传递多个参数

可以通过传递一个对象来设置多个查询字符串参数。这些参数将作为名称和值的键值对发送到服务器端。

const httpOptions = {
  params: {
    id: '123',
    name: 'John',
    email: 'john@example.com'
  }
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. 处理复杂查询参数

可以通过两种方式来处理复杂的查询字符串参数:

  • 使用编码的查询字符串参数值,这样可以避免特殊字符引起的问题。
  • 将参数值设置为数组或对象,以支持嵌套查询字符串参数。

例如,以下请求将发送包含嵌套字段和数组值的查询字符串:

const httpOptions = {
  params: {
    filter: {
      ages: [20, 30, 40],
      names: ['John', 'Mary']
    }
  }
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. 自定义参数编码

HttpClient 的 params 选项支持自定义参数编码,以便提供更精细的控制,例如限制字符集或提供某些编码格式。要使用自定义编码器,只需设置对象的 params 为 HttpHeaders 参数,并添加自定义编码器。

const httpOptions = {
  params: new HttpHeaders()
    .set('filter', 'age > 18')
    .set('format', 'json')
    .set('charset', 'utf-8')
};
this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});

以上是 HttpClient 的 params 选项的示例说明,如果您还需要具体了解其他方面的信息,请参阅 Angular 的官方文档。

reportProgress

HttpClient 的 reportProgress 选项用于在 HTTP 请求和响应过程中通知进度变化。通过将该选项设置为 true,您可以通过 HttpEvent 的事件流来获得包含进度信息的事件统计。

以下是 HttpClient 的 reportProgress 选项示例说明:

  1. 提供上传进度

如果要在文件上传期间通知进度,则可以将 reportProgress 设置为 true,并在进度事件中使用 loaded 和 total 事件。例如:

uploadFile(file: File) {
  const formData = new FormData();
  formData.append('file', file, file.name);

  const httpOptions = {
    reportProgress: true
  };

  const req = new HttpRequest(
    'POST',
    '/api/upload',
    formData,
    httpOptions
  );

  this.http.request(req).subscribe(event => {
    if (event.type === HttpEventType.UploadProgress) {
      const percentDone = Math.round((100 * event.loaded) / event.total);
      console.log(`File is ${percentDone}% uploaded`);
    } else if (event.type === HttpEventType.Response) {
      console.log(`Server response: ${event.body}`);
    }
  });
}
  1. 提供下载进度

如果要在文件下载期间通知进度,则可以将 reportProgress 设置为 true,并使用 loaded 和 total 事件警报。例如:

downloadFile() {
  const httpOptions = {
    responseType: 'blob',
    reportProgress: true
  };

  this.http.get('/api/download', httpOptions).subscribe(event => {
    if (event.type === HttpEventType.DownloadProgress) {
      const percentDone = Math.round((100 * event.loaded) / event.total);
      console.log(`File is ${percentDone}% downloaded`);
    } else if (event.type === HttpEventType.Response) {
      const blob = new Blob([event.body], {type: 'application/octet-stream'});
      saveAs(blob, 'file.zip');
    }
  });
}
  1. 提供通用进度

除了下载和上传进度之外,您还可以使用 reportProgress 选项来跟踪 HTTP 请求和响应过程的通用进度。这有助于您诊断慢速或错误的响应。例如:

fetchData() {
  const httpOptions = {
    reportProgress: true
  };

  this.http.get('/api/data', httpOptions).subscribe(event => {
    if (event.type === HttpEventType.Sent) {
      console.log('Request is sent');
    } else if (event.type === HttpEventType.ResponseHeader) {
      console.log('Received response header');
    } else if (event.type === HttpEventType.DownloadProgress) {
      console.log(`Downloaded ${event.loaded} of ${event.total} bytes`);
    } else if (event.type === HttpEventType.Response) {
      console.log('Received full response', event.body);
    }
  });
}

以上是 HttpClient 的 reportProgress 选项的示例说明,如果您还需要具体了解其他方面的信息,请参阅 Angular 的官方文档。

reponseType

HttpClient的 responseType 选项用于设置 HTTP 响应的预期响应数据类型。可以使用 responseType 选项指示 HttpClient 解析响应时预期的格式,并将响应的主体转换为合适的 JavaScript 类型。

以下是 HttpClient 的 responseType 选项示例说明:

  1. 文本响应类型

可以使用 responseType: 'text' 来接收文本类型的响应主体数据。

const httpOptions = {
  responseType: 'text'
};

this.http.get<string>(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. JSON 响应类型

可以使用 responseType: 'json' 来接收 JSON 格式的响应主体数据,该响应将被解析为 JavaScript 对象或数组。

const httpOptions = {
  responseType: 'json'
};

this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. ArrayBuffer 和 Blob 类型

可以使用 responseType 选项设置为 'arraybuffer' 和 'blob',以指定响应主体的类型。这可以用于处理二进制数据的响应,例如图片或音频文件等。

const httpOptions = {
  responseType: 'blob'
};

this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. 重写响应类型解析

如果默认的响应类型无法满足您的需求,可以通过传递responseType: 'json' 的参数来自定义响应解析逻辑。

this.http.get(URL, { responseType: 'text' }).pipe(
  map((data: string) => {
    try {
      return JSON.parse(data);
    } catch (error) {
      return null;
    }
  })
).subscribe(data => {
  console.log(data);
});

以上是 HttpClient 的 responseType 选项的示例说明,如果您还需要具体了解其他方面的信息,请参阅 Angular 的官方文档。

withCredentials

HttpClient 的 withCredentials 选项用于控制是否在跨域请求中发送和接收 cookie。默认情况下,如果跨域请求未指定 withCredentials,则浏览器不会将 cookie 发送到服务器或接收响应中的 cookie。

以下是 HttpClient 的 withCredentials 选项示例说明:

  1. 设置为 true

当将 withCredentials 设置为 true 时,浏览器将处理跨域请求,并在请求和响应中将 cookie 发送到服务器和接收响应中的 cookie。

const httpOptions = {
  withCredentials: true
};

this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});
  1. 请求未包含 withCredentials

当请求未包含 withCredentials,则浏览器不会在请求中包括 cookie,因此也无法在响应中接收 cookie。

this.http.get(URL).subscribe(data => {
  console.log(data);
});
  1. 跨域资源共享 (CORS)

在跨域请求中使用 withCredentials 时,请确保服务器支持 CORS,在使用此选项发送 cookie 时,可能会出现跨域问题。

  1. 支持跨站点资源共享 (CORS)

可以在设置 CORS HEADERS 的情况下启用跨站点资源共享。在服务器响应的 HEADER 中设置 'Access-Control-Allow-Credentials: true',以允许跨站点请求接收和发送 cookie。

accessControlHeader {
  'Access-Control-Allow-Origin': 'http://localhost:4200',
  'Access-Control-Allow-Credentials': 'true'
};

const httpOptions = {
  withCredentials: true,
  headers: new HttpHeaders(accessControlHeader)
};

this.http.get(URL, httpOptions).subscribe(data => {
  console.log(data);
});

以上是 HttpClient 的 withCredentials 选项的示例说明,如果您还需要具体了解其他方面的信息,请参阅 Angular 的官方文档。

转载自:https://juejin.cn/post/7240006787948183610
评论
请登录