我们通常开始直接在代码中使用像axios这样的第三方库。这没有错。但是,在不断变化的库,软件包,版本等世界中,直接使用这些库API可能会导致代码不一致。
一个好的做法是创建自己的抽象并将对库API的调用包装到包装器中。这将使您保持代码更加一致,并且在将来需要时也可以更轻松地切换到其他库或者程序包。这是因为您将所有对第三方库的调用都包装在一个位置,并且只要包装器接口没有更改,就可以替换包装器方法的实现以切换到新库。
让我们开始写代码
在用于发出Http请求的代码的特定情况下,我们可以创建一个名为IHttpClient的接口,然后创建一个名为HttpClient的类来实现该接口。在我们的HttpClient方法中,我们将调用axios方法。
现在,让我们假设HttpClient仅具有通用的get和post方法:
export interface IHttpClient { get(parameters: IHttpClientRequestParameters): Promise post(parameters: IHttpClientRequestParameters): Promise}
我们还需要一个接口,以将我们的参数传递给带有一个参数的get和post,以避免代码混乱。我们将其称为IHttpClientRequestParameters,它将花费一些通用时间T来定义传入的有效负载的类型(如果有)以及用于任何类型的Http请求的其他通用参数:
export interface IHttpClientRequestParameters { 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(parameters: IHttpClientRequestParameters): Promise { return new Promise((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(parameters: IHttpClientRequestParameters): Promise { return new Promise((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 { // 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(getParameters)}
总结
现在,您有了一个HttpClient,它抽象了不同的Http请求(如get或post等)并将代码封装在一个地方。在HttpClient中,您可以使用axios或者其他平台的请求库亦或其他请求协议,这样并不会污染你外部的代码。