我们通常开始直接在代码中使用像axios这样的第三方库。这没有错。但是,在不断变化的库,软件包,版本等世界中,直接使用这些库API可能会导致代码不一致。

一个好的做法是创建自己的抽象并将对库API的调用包装到包装器中。这将使您保持代码更加一致,并且在将来需要时也可以更轻松地切换到其他库或者程序包。这是因为您将所有对第三方库的调用都包装在一个位置,并且只要包装器接口没有更改,就可以替换包装器方法的实现以切换到新库。

如何在typescript中使用axios来封装一个HttpClient类-编程范儿

让我们开始写代码

在用于发出Http请求的代码的特定情况下,我们可以创建一个名为IHttpClient的接口,然后创建一个名为HttpClient的类来实现该接口。在我们的HttpClient方法中,我们将调用axios方法。

现在,让我们假设HttpClient仅具有通用的get和post方法:

export interface IHttpClient {  
get<T>(parameters: IHttpClientRequestParameters): Promise<T>  
post<T>(parameters: IHttpClientRequestParameters): Promise<T> }

我们还需要一个接口,以将我们的参数传递给带有一个参数的get和post,以避免代码混乱。我们将其称为IHttpClientRequestParameters,它将花费一些通用时间T来定义传入的有效负载的类型(如果有)以及用于任何类型的Http请求的其他通用参数:

export interface IHttpClientRequestParameters<T> {  url: string  requiresToken: boolean  payload?: T}

这是请求参数接口的每个属性的详细说明:

url:这是我们需要向其发出请求的API端点的完整url(必须包含查询字符串参数)

requireToken:这是一个布尔值,指示我们的请求是否还必须添加身份验证令牌(即Jwt令牌)

有效负载:这是POST或PUT请求的有效负载,因此是可选的。现在,我们可以编码HttpClient类,以实现IHttpClient接口并使用axios。首先,从axios导入所需的内容,并编写尚未实现的HttpClient类的初始声明:

import axios, { AxiosRequestConfig, AxiosError, AxiosResponse } from 'axios'export class HttpClient implements IHttpClient {  // ... implementation code will go here}

现在,按照界面中的定义添加get方法的实现。请注意,这里我使用的是Promise语法,但是欢迎您使用async / await语法。我们的get方法将使用IHttpClientRequestParameters的实例并返回Promise:

get<T>(parameters: IHttpClientRequestParameters): Promise<T> {  return new Promise<T>((resolve, reject) => {    // extract the individual parameters    const { url, requiresToken } = parameters     // axios request options like headers etc    const options: AxiosRequestConfig = {      headers: {}    }    // if API endpoint requires a token, we'll need to add a way to add this.    if (requiresToken) {      const token = this.getToken()      options.headers.RequestVerificationToken = token    }    // finally execute the GET request with axios:    axios      .get(url, options)      .then((response: any) => {        resolve(response.data as T)      })      .catch((response: any) => {        reject(response)      })  })}

同样,现在添加接口中定义的post方法的实现。像get一样,我们的post方法将采用IHttpClientRequestParameters的实例并返回Promise:

post<T>(parameters: IHttpClientRequestParameters): Promise<T> {  return new Promise<T>((resolve, reject) => {    const { url, payload, requiresToken } = parameters    // axios request options like headers etc    const options: AxiosRequestConfig = {      headers: {}    }    // if API endpoint requires a token, we'll need to add a way to add this.    if (requiresToken) {      const token = this.getToken()      options.headers.RequestVerificationToken = token    }    // finally execute the GET request with axios:    axios      .post(url, payload, options)      .then((response: any) => {        resolve(response.data as T)      })      .catch((response: any) => {        reject(response)      })  })}

现在,您可以导出HttpClient的实例并在整个代码中使用:

export const httpClient = new HttpClient()

这是一个示例,我们使用它来获取IItem类型的“项目”列表:

fetchItems(): Promise<IItem[]> {  // prepare our request parameters  const getParameters: IHttpClientPostParameters = {    url: 'http://yourapiurl/items',    requiresToken: false  }  // just return httpClient.get (which is a promise) or again use async/await if you prefer  return httpClient.get<IItem[]>(getParameters)}

总结

现在,您有了一个HttpClient,它抽象了不同的Http请求(如get或post等)并将代码封装在一个地方。在HttpClient中,您可以使用axios或者其他平台的请求库亦或其他请求协议,这样并不会污染你外部的代码。