基于axios封装请求

195 阅读1分钟

基于axios封装请求

安装

pnpm i axios

创建实例

import axios, { AxiosError, AxiosInstance } from 'axios'

function createRequestInstance(url: string): AxiosInstance {
	const instance = axios.create({
		timeout: 1000 * 60 * 10,
		withCredentials: false,
		baseURL: `${url}/`,
	})
	return instance
}
//创建一个axios实例
const request = createRequestInstance('http://10.10.24.58:3000')

export default request

新增错误class

新建error.ts

import { AxiosError } from 'axios'

//自定义错误返回类型(具体可以跟后端同学商量决定)
export type ErrorResponse = {
	status: number
	code: number
	msg: string
}

class AxRequestError extends Error {
	data: ErrorResponse | undefined

	raw: AxiosError

	isUnAuthorized = false

	isServerError = false

	errCode?: number

	isNetError = false

	message: string

	constructor(status: number, message: string, raw: AxiosError, data?: ErrorResponse) {
		super(message) // ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错。
		this.data = data
		this.raw = raw
		this.isUnAuthorized = status === 401 //一般是身份验证不通过,token过期
		this.isServerError = status >= 500
		this.errCode = data?.code
		this.message = `${message || raw?.message || data?.msg || ''}`
		if (message.includes('getaddrinfo ENOTFOUND') || message === 'Network Error') {
			this.message = 'network error'
			this.isNetError = true
		} else if (['no token present in request'].includes(message)) {
			this.message = 'login expired'
		}
	}
}

export default AxRequestError

新增错误处理器 handleError.ts

import { AxiosError } from 'axios'
import AxRequestError, { ErrorResponse } from './error'

export function handelError(error: AxiosError | AxRequestError): AxRequestError {
	const err = error instanceof AxRequestError ? error : new AxRequestError(error.response?.status || 1, error.message, error, error.response?.data as ErrorResponse)
	return err
}

请求拦截器

在instance.ts 实例文件中新增请求拦截器,添加用户身份验证、多语言、自定义headers等设置

//伪方法 具体根据业务逻辑实现
const getToken = () => {
	return ''
}
//请求拦截器
request.interceptors.request.use(config => {
	const token = getToken() 
	const headers = config.headers || {}
	config.headers = {
		...headers,
		Authorization: `${headers.Authorization || token || ''}`,
		language: 'zh', //适用于多语言环境,
	} 
	return config
})

响应拦截器

//响应拦截器
request.interceptors.response.use(undefined, (err: AxRequestError) => {
	err = handelError(err)
	if (err.isUnAuthorized) {
		//todo退出登录
	}
	//其他错误处理

	return Promise.reject(err)
})

公共请求方法

import { AxiosResponse, AxiosRequestConfig } from 'axios'
import request from './instance'

/* 导出封装的请求方法以及公共方法 */
const $api = {
	get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> {
		return request.get(url, config)
	},
	post<T = any, R = AxiosResponse<T>>(url: string, data?: object, config?: AxiosRequestConfig): Promise<R> {
		return request.post(url, data, config)
	},
	put<T = any, R = AxiosResponse<T>>(url: string, data?: object, config?: AxiosRequestConfig): Promise<R> {
		return request.put(url, data, config)
	},
	delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R> {
		return request.delete(url, config)
	},
	patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R> {
		return request.patch(url, data, config)
	},

	async test(): Promise<AxiosResponse> {
		const res = await request.get('/test')
		return res
	},
}

export default $api

在main.ts绑定公共请求方法

import $api from '@/service/requestList'

app.config.globalProperties.$api = $api

配置生产环境和开发环境

新增env.ts

import { isUndef } from '@/utils/is'

// 正式环境
export const ENV = {
	APP_API_BASE: 'http://10.10.24.58:3000',
	IS_DEV: '',
	NODE_ENV: 'production',
	IS_TEST: '',
}

// 测试环境
export const ENV_DEV = {
	...ENV,
	APP_API_BASE: 'http://10.10.24.58:3001',
	IS_DEV: 'true',
	NODE_ENV: 'development',
	IS_TEST: 'true',
}

export type EnvKey = keyof typeof ENV

const isTestEnv = process.env.NODE_ENV === 'development' || ['test.xxx.com'].includes(location.host)

// const isTestEnv = false
export function getProcessEnv(key: EnvKey): string | void {
	if (isTestEnv) {
		if (!isUndef(ENV_DEV[key])) {
			return ENV_DEV[key]
		}
		return ''
	}
	if (!isUndef(ENV[key])) {
		return ENV[key]
	}
}

在instance.ts中引入

import { getProcessEnv } from '@/global/env'
const request = createRequestInstance(getProcessEnv('APP_API_BASE') || '')

测试一下

import $api from '@/service/request'

$api.get('/test').then(res => {
	console.info('res:', res)
})
$api.test().then(res => {
	console.info('res:', res)
})