目錄
前言
一、axios中的常見類型
1. AxiosInstance
2. AxiosRequestConfig
3. AxiosResponse
4. AxiosError
二、axios封裝步驟
三、封裝后的完整代碼
1. 基礎封裝
2. 高級封裝
前言
為了實現統一的網絡請求處理和管理,在日常開發中我們常常封裝 axios,來實現統一配置、設置請求攔截器和響應攔截器、錯誤處理等。
TypeScript可以給項目提供類型檢查和類型推導,axios請求回來的數據也會受其檢查。本文將提供axios結合ts寫法的封裝步驟和代碼。
一、axios中的常見類型
1. AxiosInstance
表示axios請求的配置選項,包括URL、方法、頭部、參數等。
2. AxiosRequestConfig
表示一個axios實例的類型,可以用于創建自定義配置的axios實例。
3. AxiosResponse
表示axios響應的數據結構,包括狀態碼、響應頭和響應數據。
4. AxiosError
表示axios請求發生錯誤時的錯誤對象,包括錯誤消息、請求配置和響應信息(如果有)。
注意:如果沒有跟類型,ts也會自動推到成相應類型。可以不寫,但不能錯寫。
二、axios封裝步驟
1.?安裝依賴
在項目根目錄下,使用 npm 或 yarn 命令安裝 axios 和 @types/axios(用于提供 axios 的類型定義文件)
pnpm install axios @types/axios
2.?創建封裝文件
在項目中創建一個新的文件,例如 request.ts
,用于封裝 axios。可以根據項目需求結構化地組織這些文件。文件名根據個人習慣來,大都取 axios 、request 、http等。
3.?導入 axios
在 request.ts
?文件中導入 axios 模塊。
4. 添加默認配置
根據需要,在請求方法中設置默認的請求頭、超時時間、響應數據格式等配置項。
5. 定義返回的數據類型
根據后端返回的數據,設置統一的請求結果接口。
6.?添加攔截器
如果需要使用攔截器,可以在 api.ts 文件中定義請求攔截器和響應攔截器,并注冊到 axios 中。
7. 封裝請求方法
根據項目需求,定義請求方法,例如 GET、POST、PUT、DELETE 等。可以使用泛型來指定請求和響應的數據類型,增加類型安全性。
8.?導出方法/實例
在?request.ts
?文件末尾,將封裝的請求方法進行導出。
三、封裝后的完整代碼
1. 基礎封裝
使用對象字面量方式創建一個單例的axios實例。
// 導入axios和所需的類型
import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'// 默認配置
const service: AxiosInstance = axios.create({baseURL: import.meta.env.VITE_API_BASE || '/' // 設置API的基本URL,默認為根路徑
})// 請求攔截器,對請求配置進行一些處理或設置
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {return config},(error: AxiosError) => {return Promise.reject(error)}
)// 響應攔截器,對響應結果進行處理或判斷
service.interceptors.response.use((response: AxiosResponse) => {if (response.status === 200) {return response.data}return Promise.reject() // 如果響應狀態不是200,則返回一個拒絕的Promise},(error: AxiosError) => {return Promise.reject(error)}
)export default service // 導出封裝好的axios實例// 定義結果接口Result
export interface Result<T = unknown> {message: stringcode: numberdata: T[key: string]: any // 其他任意屬性
}export const http = {// 發送GET請求的方法,可指定數據類型T,并返回一個Promise對象,其值為Result<T>類型get<T = any>(url: string, data?: object): Promise<Result<T>> {return service.get<T, Result<T>>(url, data);},// 發送POST請求的方法,同樣可指定數據類型T,并返回一個Promise對象post<T = any>(url: string, data?: object): Promise<Result<T>> {return service.post<T, Result<T>>(url, data);},// 發送PUT請求的方法,同樣可指定數據類型T,并返回一個Promise對象put<T = any>(url: string, data?: object): Promise<Result<T>> {return service.put<T, Result<T>>(url, data);},// 發送DELETE請求的方法,同樣可指定數據類型T,并返回一個Promise對象delete<T = any>(url: string): Promise<Result<T>> {return service.delete<T, Result<T>>(url);},
};
2. 高級封裝
相比基礎封裝,高級封裝通過類的方式來創建實例,并將請求方法封裝在類的原型上。
相比之下,這種方法更加靈活,可以創建多個不同配置的axios實例,也可以在實例中添加其他自定義的方法和屬性。此外,高級封裝還將請求方法統一封裝在一個類中,結構更加清晰,易于維護和擴展。
// 先創建一個類,給類添加1個屬性 instance代表axios的實例 構造函數傳遞配置 config配置比如全局的baseURL timeout
?
import axios from "axios";
import type {AxiosInstance,AxiosError,AxiosResponse,AxiosRequestConfig,
} from "axios";
?
// interface Result<T = any> {
// ? data: T;
// ? success: boolean;
// }
?
class Request {// 限制創建的實例必須是axios的實例private instance: AxiosInstance;// 這個config是不能亂寫的,axios對創建的配置有限制的constructor(config: AxiosRequestConfig) {this.instance = axios.create(config);
?// 接下來配置axios實例身上的全局配置,比如攔截器this.instance.interceptors.request.use((config: AxiosRequestConfig) => {return config;},(error: AxiosError) => {return Promise.reject(error);});
?this.instance.interceptors.response.use((response: AxiosResponse) => {return response.data;},(error: AxiosError) => {return Promise.reject(error);});}
?// 公共方法,因為不知道返回值的類型fetchData<T>(options: AxiosRequestConfig): Promise<T> {// 將私有的instance上面發請求的操作,封裝到這個實例方法request中,這個方法的返回值應該是一個promise對象return new Promise((resolve, reject) => {this.instance.request<any, T>(options).then((res) => {resolve(res);}).catch((err) => {reject(err);});});}
?// 調用上面封裝的實例方法request,來實現get / post / delete / put 方法的快捷調用get<T>(options: AxiosRequestConfig): Promise<T> {return this.fetchData<T>({ ...options, method: "GET" });}
?post<T>(options: AxiosRequestConfig): Promise<T> {return this.fetchData({ ...options, method: "POST" });}
?put<T>(options: AxiosRequestConfig): Promise<T> {return this.fetchData({ ...options, method: "PUT" });}
?delete<T>(options: AxiosRequestConfig): Promise<T> {return this.fetchData({ ...options, method: "DELETE" });}
}
?
// 到處新new出來的實例
export const http = new Request({baseURL: "https://mock.mengxuegu.com/mock/6323def2b4c53348ed2bc5d7/example",
});