作为一个前端开发, 免不了要调用各种各样的后端接口.
随着项目的复杂程度增长, 接口要传送的参数和返回的数据结构会变得越来越复杂.字段越堆越多, 嵌套一层又一层, 一不小心就会把我们给气死. 浏览器也会发出如下的叹息:
然后就又是一遍一遍的接口文档和代码比对着看,以期望找出其中的不同. 或者写了很多的 console.log 在控制台上苦苦寻觅......
不啰嗦了, 直接上代码!
基于axios + typescript的接口封装案例
首先创建两个文件
index.ts 基于axios封装 Api 类
// src/api/index.ts
import axios from 'axios'
import type {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios'
// 用于具体接口根据需要修改当次请求的axios配置
export type CustomConfig = {
raw?: boolean
}
class Api {
// axios 实例
instance: AxiosInstance
// 基础配置,url和超时时间
baseConfig: AxiosRequestConfig = {baseURL: '/', timeout: 60000}
constructor(config: AxiosRequestConfig) {
// 创建axios实例
this.instance = axios.create(Object.assign(this.baseConfig, config))
this.instance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 请求拦截
// 可以统一配置headers 如加token
// config.headers!.Authorization = token
return config
},
(err: any) => {
return Promise.reject(err)
}
)
this.instance.interceptors.response.use(
(res: AxiosResponse & {config: CustomConfig}) => {
// 响应拦截 可以在其中预处理返回数据
return res.config.raw ? res.data : res.data.data
},
(err: any) => {
// 这里用来处理http常见错误,进行全局提示
let message = ''
switch (err.response?.status) {
case 400:
message = '请求错误(400)'
break
default:
message = `连接出错(${err.response.status})!`
}
// 这里是AxiosError类型,所以一般我们只reject我们需要的响应即可
return Promise.reject(err.response)
}
)
}
// 定义请求方法
public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.instance.request(config)
}
//在这里 get 函数接受一个泛型参数 并返回这个类型对应的 Promise 泛型
public get<T = any>(
url: string,
config?: AxiosRequestConfig & CustomConfig
): Promise<T> {
return this.instance.get(url, config)
}
public post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.instance.post(url, data, config)
}
}
export default Api
然后在 req.ts 中编写我们实际的接口
// src/api/req.ts
import type {AxiosRequestConfig} from 'axios'
import Api, {CustomConfig} from '@/api/index'
// 实例化接口类
export const api = new Api({
// 这里填上我们接口的统一前缀
baseURL: '/api/v1/'
})
// 看下面post函数的注释, 大同小异
export const get = <T = any, U = any>(url, _config?: CustomConfig) => {
return function(params?: T, config?: AxiosRequestConfig) {
return api.get<U>(url, {..._config, ...config, params})
}
}
// 使用函数柯里化对每一个api连接都生成一个函数
// 这里的 post 函数是一个泛型函数
// T 表示请求参数的类型
// U 表示返回参数的类型
// 这样只要我们在编写接口函数的时候写明类型, 在调用的时候就能直接获取类型提示了
export const post = <T = any, U = any>(url, _config?: CustomConfig) => {
return function (data?: T, config?: AxiosRequestConfig) {
return api.post<U>(url, data, {..._config, ...config})
}
}
/////////////////////////////////
// 在这里可以声明我们具体的接口了
// 用来约束login接口的入参
type LoginParam = {username: string, password: string}
// 用来标明login接口的出参
type LoginRes = {token: string}
export const login = post<LoginParam, LoginRes>('permission/login')
看一下调用的效果吧😄
// 在某个异步函数中
const res = await login({username: '小明', password: '123456'})
这不, 妥妥的提示出来了
最后, 欢迎点赞收藏啥的