近日在使用react+typescript制作項(xiàng)目,發(fā)現(xiàn)ts的使用方法與js的差別相當(dāng)巨大。其中就包括axios的封裝方法,網(wǎng)上找的各種教程也沒看懂。于是自己花了將近一天的時(shí)間,通過各方面的學(xué)習(xí),總算自己封裝好了一個(gè)ts版的axios。因?yàn)橹岸际鞘褂胿ue來開發(fā)的,所以這個(gè)封裝好的axios,我想盡量讓它的調(diào)用的方式跟原來的vue的調(diào)用方式差不多,因?yàn)槲艺J(rèn)為原來的調(diào)用方式非常美觀且易于管理。
//vue的調(diào)用方式
import { request } from './request'
//參數(shù)是 地址:url、請(qǐng)求參數(shù):params、僅用于當(dāng)前api的配置config——該參數(shù)選填
export const LoginApi = params => request.post('/user/login', params, {timeout: 15000});
...更多的api
為了達(dá)到上面的調(diào)用方式,于是自己實(shí)現(xiàn)了封裝。
以下為詳細(xì)實(shí)現(xiàn)方法:
第一步
安裝:axios
// -S 意為該依賴包將會(huì)打包至生產(chǎn)環(huán)境
cnpm i axios -S
第二步
1、在 src 文件夾下新建 api 文件夾——該文件夾可隨意命名,不過推薦使用api來命名
2、在 api 文件夾里新建request.ts文件,下為源碼(下面的代碼可以直接復(fù)制出來使用)
import axios, { AxiosRequestConfig, AxiosRequestHeaders } from 'axios';
import { message } from 'antd'
//基礎(chǔ)URL,axios將會(huì)自動(dòng)拼接在url前
//process.env.NODE_ENV 判斷是否為開發(fā)環(huán)境 根據(jù)不同環(huán)境使用不同的baseURL 方便調(diào)試
let baseURL = process.env.NODE_ENV === 'development'? '' : 'https://your.domain.com/api';
//默認(rèn)請(qǐng)求超時(shí)時(shí)間
const timeout = 30000;
//創(chuàng)建axios實(shí)例
const service = axios.create({
timeout,
baseURL,
//如需要攜帶cookie 該值需設(shè)為true
withCredentials: true
});
//統(tǒng)一請(qǐng)求攔截 可配置自定義headers 例如 language、token等
service.interceptors.request.use(
(config: AxiosRequestConfig) => {
//配置自定義請(qǐng)求頭
let customHeaders: AxiosRequestHeaders = {
language: 'zh-cn'
};
config.headers = customHeaders;
return config
},
error => {
console.log(error)
Promise.reject(error)
}
)
//axios返回格式
interface axiosTypes<T>{
data: T;
status: number;
statusText: string;
}
//后臺(tái)響應(yīng)數(shù)據(jù)格式
//###該接口用于規(guī)定后臺(tái)返回的數(shù)據(jù)格式,意為必須攜帶code、msg以及result
//###而result的數(shù)據(jù)格式 由外部提供。如此即可根據(jù)不同需求,定制不同的數(shù)據(jù)格式
interface responseTypes<T>{
code: number,
msg: string,
result: T
}
//核心處理代碼 將返回一個(gè)promise 調(diào)用then將可獲取響應(yīng)的業(yè)務(wù)數(shù)據(jù)
const requestHandler = <T>(method: 'get' | 'post' | 'put' | 'delete', url: string, params: object = {}, config: AxiosRequestConfig = {}): Promise<T> => {
let response: Promise<axiosTypes<responseTypes<T>>>;
switch(method){
case 'get':
response = service.get(url, {params: { ...params }, ...config});
break;
case 'post':
response = service.post(url, {...params}, {...config});
break;
case 'put':
response = service.put(url, {...params}, {...config});
break;
case 'delete':
response = service.delete(url, {params: { ...params }, ...config});
break;
}
return new Promise<T>((resolve, reject) => {
response.then(res => {
//業(yè)務(wù)代碼 可根據(jù)需求自行處理
const data = res.data;
if(data.code !== 200){
//特定狀態(tài)碼 處理特定的需求
if(data.code == 401){
message.warn('您的賬號(hào)已登出或超時(shí),即將登出...');
console.log('登錄異常,執(zhí)行登出...');
}
let e = JSON.stringify(data);
message.warn(`請(qǐng)求錯(cuò)誤:${e}`);
console.log(`請(qǐng)求錯(cuò)誤:${e}`)
//數(shù)據(jù)請(qǐng)求錯(cuò)誤 使用reject將錯(cuò)誤返回
reject(data);
}else{
//數(shù)據(jù)請(qǐng)求正確 使用resolve將結(jié)果返回
resolve(data.result);
}
}).catch(error => {
let e = JSON.stringify(error);
message.warn(`網(wǎng)絡(luò)錯(cuò)誤:${e}`);
console.log(`網(wǎng)絡(luò)錯(cuò)誤:${e}`)
reject(error);
})
})
}
// 使用 request 統(tǒng)一調(diào)用,包括封裝的get、post、put、delete等方法
const request = {
get: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('get', url, params, config),
post: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('post', url, params, config),
put: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('put', url, params, config),
delete: <T>(url: string, params?: object, config?: AxiosRequestConfig) => requestHandler<T>('delete', url, params, config)
};
// 導(dǎo)出至外層,方便統(tǒng)一使用
export { request };
3、新建index.ts文件,導(dǎo)出對(duì)應(yīng)的api
import { request } from './request'
//登錄
export const LoginApi = <T>(params: any) => request.post<T>('/user/login', params, {timeout: 15000});
如此一來,就能像vue一樣導(dǎo)出和調(diào)用了
使用示例
import { LoginApi } from '@/api'
interface loginTypes{
auth: Array<string>,
userInfo: {
account: string,
username: string
},
token: string
}
LoginApi<loginTypes>(data).then(res => {
//登錄成功。處理區(qū)域...
}).catch(err => {
//登錄失敗。處理區(qū)域...
})