基础封装
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
class AxiosService {
private axiosInstance: AxiosInstance
constructor() {
this.axiosInstance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
})
this.initInterceptor()
}
private initInterceptor() {
this.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在请求发送之前做些什么
return config
},
(error: any) => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
this.axiosInstance.interceptors.response.use(
(response: AxiosResponse<any>) => {
// 对响应数据做些什么
return response
},
(error: any) => {
// 对响应错误做些什么
return Promise.reject(error)
}
)
}
public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance.get<T>(url, config)
}
public post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.post<T>(url, data, config)
}
public put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.put<T>(url, data, config)
}
public delete<T = any>(
url: string,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.delete<T>(url, config)
}
}
export const axiosService = new AxiosService()
这里,我们首先使用 axios.create 方法创建了一个基本的 Axios 实例,设置了 baseURL 和 timeout,然后初始化了请求和响应拦截器,以便在请求发送和响应到达时进行适当的处理。
接下来,我们在 AxiosService 类中定义了一些公共方法来处理 get,post,put 和 delete 请求。这些方法都是通过基本的 Axios 实例来实现的。
最后,我们导出了一个 axiosService 实例,以便在 Vue 组件或其他地方使用。这样,我们就可以轻松地从代码中的任何地方发出 HTTP 请求,而无需在每个组件中都重复定义 Axios 实例。
我们可以在 initInterceptor() 方法中添加一个请求拦截器,用于在每个请求之前向请求头中添加 token。以下是修改后的代码:
...
private initInterceptor() {
// 添加请求拦截器
this.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在请求发送之前做些什么
const token = localStorage.getItem('token')
if (token) {
// 添加 token 到请求头
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error: any) => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
...
在这里,我们在 initInterceptor() 方法中添加了一个请求拦截器,用于在请求发送之前将 token 添加到请求头中。我们首先使用 localStorage 从本地存储中获取 token,然后将其添加到请求头中。
这样,在每个请求发送之前,都会调用这个请求拦截器,并在请求头中添加 token。这使得我们不必在每个请求中都手动添加 token,从而提高了代码的可重用性。
在 initInterceptor() 方法中添加一个响应拦截器,用于处理 HTTP 响应中的错误。以下是修改后的代码:
...
// 添加响应拦截器
this.axiosInstance.interceptors.response.use(
(response: AxiosResponse<any>) => {
// 对响应数据做些什么
return response
},
(error: any) => {
// 对响应错误做些什么
if (error.response) {
// 如果服务器返回错误状态码
switch (error.response.status) {
case 401:
// 未授权,跳转到登录页
break
case 404:
// 请求的资源不存在
break
default:
// 其他错误
break
}
} else if (error.request) {
// 如果请求发出去没有收到响应
console.log(error.request)
} else {
// 其他错误
console.log('Error', error.message)
}
return Promise.reject(error)
}
)
}
...
在这里,我们添加了一个响应拦截器,用于处理 HTTP 响应中的错误。如果服务器返回错误状态码,我们可以在这里进行处理。例如,如果返回状态码为 401,表示未授权,我们可以将用户重定向到登录页面。如果返回状态码为 404,则表示请求的资源不存在。对于其他错误,我们可以根据需要进行处理。如果请求发出去没有收到响应,则 error.request 为请求的实例。如果出现其他错误,则 error.message 包含错误的描述。
在响应拦截器中可以判断一些常见的后端返回结果,例如:
success字段为false或0,表示请求失败。code字段为某个错误码,例如 400、401、404 等。message字段包含错误信息,可以用来提示用户。
以下是修改后的完整代码:
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
enum ResponseCode {
Success = 0, // 请求成功
Unauthorized = 401, // 未授权
NotFound = 404, // 资源不存在
InternalServerError = 500, // 服务器内部错误
}
interface ResponseData<T = any> {
success: boolean;
code: ResponseCode;
message: string;
data?: T;
}
class AxiosService {
private axiosInstance: AxiosInstance
constructor() {
this.axiosInstance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
})
this.initInterceptor()
}
private initInterceptor() {
// 添加请求拦截器
this.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在请求发送之前做些什么
const token = localStorage.getItem('token')
if (token) {
// 添加 token 到请求头
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error: any) => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
this.axiosInstance.interceptors.response.use(
(response: AxiosResponse<ResponseData>) => {
// 对响应数据做些什么
const { success, code, message, data } = response.data
if (!success || code !== ResponseCode.Success) {
// 请求失败或者出现错误
console.error(`[${code}] ${message}`)
return Promise.reject(new Error(message))
}
return data
},
(error: any) => {
// 对响应错误做些什么
if (error.response) {
// 如果服务器返回错误状态码
switch (error.response.status) {
case ResponseCode.Unauthorized:
// 未授权,跳转到登录页
break
case ResponseCode.NotFound:
// 请求的资源不存在
break
default:
// 其他错误
break
}
} else if (error.request) {
// 如果请求发出去没有收到响应
console.log(error.request)
} else {
// 其他错误
console.log('Error', error.message)
}
return Promise.reject(error)
}
)
}
public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance.get<T>(url, config)
}
public post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.post<T>(url, data, config)
}
public put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.put<T>(url, data, config)
}
public delete<T = any>(
url: string,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.delete<T>(url, config)
}
}
export const axiosService = new AxiosService()
接下来就是使用这个工具类了
下面是一个使用封装好的 axios 工具类进行登录的例子:
// import axiosService from './axiosService'
interface LoginParams {
username: string;
password: string;
}
interface LoginResult {
token: string;
}
export async function login(params: LoginParams): Promise<LoginResult> {
try {
const response = await axiosService.post<LoginResult>('/login', params)
// 处理登录成功逻辑
return response
} catch (error) {
// 处理登录失败逻辑
return Promise.reject(error)
}
}