typescript 二次封装 axios轮子

typescript和java很多类似的地方,javaScript 只会在 运行时 才去做数据类型检查,而 TypeScript 作为静态类型语言,其数据类型是在 编译期间 确定的,编写代码的时候要明确变量的数据类型。使用 TypeScript 后,这些低级错误将不再发生。规范后用起来很舒服,能轻易知道自己错在哪。下面就是axios的二次封装。
为了代码规范化

首先在路径下utils/http 文件下需要三个ts分步文件 core.ts (核心类的封装) index.ts(到处类的封装) types.ts(所用到的类型封装)
在这里插入图片描述
首先核心类的封装(core.ts)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import axios from 'axios'
import {<!-- --> AxiosInstance, AxiosRequestConfig, AxiosResponse, Method } from 'axios'
import {<!-- --> IResponseData, codeMessage } from './types';
import {<!-- -->successMessage,errorMessage} from '../messageTips'

class Http {<!-- -->
    private service: AxiosInstance
    //    构造器
    constructor(config: AxiosRequestConfig) {<!-- -->
        //    创造实例
        this.service = axios.create(config)
        // 首先配置响应拦截
        this.service.interceptors.request.use((config: AxiosRequestConfig) => {<!-- -->
            /**
             * 实现自己的业务逻辑
             * 1.开启全屏加载动画之类
             * 2.数据加密config。data
             * 3.给请求头添加信息等(token 结合sessionStorage,localStorage,vuex这些)
             *
             */
            return config

        }, error => {<!-- -->

            /* 请求错误的业务逻辑
             1. 关闭全屏loading动画
             2. 重定向到错误页
           */
            return Promise.reject(error)// 为了可以在代码中catch到错误信息
        })//end request.use

        this.service.interceptors.response.use((response: AxiosResponse) => {<!-- -->
            /*
          1. 关闭全屏loading动画
          2. 数据解密
          3. 根据 response.data.code 做不同的错误处理
          4. ……
          */
            const data = response.data
            const {<!-- --> code } = data//解构赋值
            if (code !== '000000') {<!-- -->
                // 这里面处理事务这些,发出警告等
                errorMessage(codeMessage[code])
            }
            return response.data
        }, error => {<!-- -->
            return Promise.reject(error)
        })//end response.use
    } //end constructor

// get<T>这个T 是对应后面返回数值data   Promise<IResponseData<T>>  里面的T
    public get<T>(url: string, params?: any): Promise<IResponseData<T>> {<!-- -->
        return this.service.get(url, params)
    }

    public post<T>(url: string, params: any,): Promise<IResponseData<T>> {<!-- -->
        return this.service.post(url, params)
    }

    public request<T>(method: Method, url: string, data?: any): Promise<IResponseData<T>> {<!-- -->
        return this.service.request({<!-- --> method, url, data })
    }
}
export default Http

type.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export interface IResponseData<T> {<!-- -->
  status: number;
  message?:string;
  data:T;
  code: string;
}
 export const codeMessage: {<!-- --> [key: number]: string } = {<!-- -->
  200: "服务器成功返回请求的数据。",
  201: "新建或修改数据成功。",
  202: "一个请求已经进入后台排队(异步任务)。",
  204: "删除数据成功。",
  400: "发出的请求有错误,服务器没有进行新建或修改数据的操作。",
  401: "用户没有权限(令牌、用户名、密码错误)。",
  403: "用户得到授权,但是访问是被禁止的。",
  404: "发出的请求针对的是不存在的记录,服务器没有进行操作。",
  406: "请求的格式不可得。",
  410: "请求的资源被永久删除,且不会再得到的。",
  422: "当创建一个对象时,发生一个验证错误。",
  500: "服务器发生错误,请检查服务器。",
  502: "网关错误。",
  503: "服务不可用,服务器暂时过载或维护。",
  504: "网关超时。",
};

index.ts 实例出去

1
2
3
4
5
6
7
import Http from "./core";
import {<!-- -->AxiosRequestConfig} from 'axios'
const config:AxiosRequestConfig = {<!-- -->
    baseURL:'/api',//按照自己的来写
    timeout:10000//响应超时
}
export default new Http(config) //创建实例对象

使用如下,建议单独封装一下,加一个api文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import http from "./utils/http/index";
   http
      .get("/user-tb/userlist")
      .then((res) => {<!-- -->
        console.log("这个是get成功");
        console.log(res);
      })
      .catch((err) => {<!-- -->
        console.log("失败1");
        console.log(err);
      });
    http
      .get("/user-tb/find/1")
      .then((res) => {<!-- -->
        console.log(2);
        console.log(res);
      })
      .catch((err) => {<!-- -->
        console.log("失败2");
        console.log(err);
      });
    http
      .request("get", "/user-tb/find/1")
      .then((res) => {<!-- -->
        console.log(res);
      })
      .catch((err) => {<!-- -->
        console.log("失败3");
        console.log(err);
      });
  },

接下来就是对于有些泛型接口的理解,比如这个T

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export interface AxiosResponse {<!-- -->
  data: any; // 服务端返回的数据
  status: number; // HTTP 状态码
  statusText: string; // 状态消息
  headers: any; // 响应头
  config: AxiosRequestConfig; // 请求配置对象
  request: any; // 请求的 XMLHttpRequest 对象实例
}




export interface AxiosResponse<T = any> {<!-- -->
  data: T; // 服务端返回的数据
  status: number; // HTTP 状态码
  statusText: string; // 状态消息
  headers: any; // 响应头
  config: AxiosRequestConfig; // 请求配置对象
  request: any; // 请求的 XMLHttpRequest 对象实例
}

这里我们给 AxiosResponse 接口添加了泛型参数 T,T=any 表示泛型的类型参数默认值为 any。
有了这个泛型参数以后,我们在发送请求时就可以指定返回的data的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 获取用户api
export function getUserInfo<T>() {<!-- -->
  return axios.get<ResponseData<T>>('/getuser')
    .then(res => res.data)
    .catch(err => console.error(err))
}

// 调用getUser发出请求

// 期望返回data的类型
interface User {<!-- -->
  name: string
  age: number
}

async function test() {<!-- -->
  // user 被推断出为
  // {<!-- -->
  //  data: { name: string, age: number },
  //  ...
  // }
  const user = await getUser<User>()
}

新手小白,多多关照哦