react+typescript 封裝 axios

近日在使用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ū)域...
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容