项目使用代码 个人封装 可直接复制粘贴使用。
项目是基于react的 需结合自己项目使用框架进行适当修改。
import { message as Message } from 'antd'
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
export const PRD_URL_PREFIX_ACTIVITY = '/api/activity/'
export const PRD_URL_PREFIX_BASE = '/api'
export type IErrorHandler = (statusCode: number, message: string) => void
const defaultErrorHandler: IErrorHandler = (statusCode, message) => {
Message.error(typeof message === 'string' ? message : JSON.stringify(message))
}
export interface IRequestConfig extends AxiosRequestConfig {
// 是否阻止提示错误消息
suppressErrorMessage?: boolean
}
export interface IResponse {
status: string
data: T
message?: string
}
export interface IResponse2 {
code: string | number
data: T
message: string
}
export class HttpClient {
// 是否为生产环境
private isProduction: boolean = false
constructor(isProduction: boolean, errorHandler?: IErrorHandler) {
this.isProduction = Boolean(isProduction)
if (errorHandler) {
this.errorHandler = errorHandler
}
}
// 错误处理函数
public errorHandler: IErrorHandler = (statusCode: number, message: string) => {
console.error(message)
}
/**
* 为发布环境处理URL
*/
public dealUrlForPrd(url: string) {
return this.isProduction ? url.replace(/^\/?api/g, '/marketApi') : url
}
/**
* 转义查询参数
*/
public encode(queryString?: string | null): string {
if (!queryString) {
return ''
}
return encodeURIComponent(queryString.replace(/[-[\]{}()*+?.,\\/^$|#]/g, '\\$&'))
}
/**
* get查询
*/
public async get(url: string, requestConfig: IRequestConfig = {}) {
const { suppressErrorMessage, ...config } = requestConfig
try {
const response: AxiosResponse = await axios({
url: this.getUrlWithTimestamp(this.dealUrlForPrd(url)),
method: 'GET',
headers: {
'content-type': 'application/json; charse=UTF-8',
},
...config,
})
return this.handleSuccess(response, suppressErrorMessage)
} catch (e) {
this.handleError(e, suppressErrorMessage)
throw e
}
}
/**
* post查询
*/
public async post(
url: string,
obj?: object | string,
requestConfig: IRequestConfig = {}
): Promise {
const { suppressErrorMessage, ...config } = requestConfig
let data = {}
if (typeof obj === 'string') {
try {
data = JSON.parse(obj)
} catch (e) {
throw new Error(`请求参数解析失败\n${obj}\n${url}\n${e}`)
}
} else if (typeof obj === 'object') {
data = obj
}
try {
const response: AxiosResponse = await axios({
url: this.dealUrlForPrd(url),
method: 'POST',
headers: {
'content-type': 'application/json; charse=UTF-8',
},
data,
...config,
})
return this.handleSuccess(response, suppressErrorMessage)
} catch (e) {
this.handleError(e, suppressErrorMessage)
throw e
}
}
/**
* del请求
*/
public async del(url: string, requestConfig: IRequestConfig = {}): Promise {
const { suppressErrorMessage, ...config } = requestConfig
try {
const response: AxiosResponse = await axios({
url: this.getUrlWithTimestamp(this.dealUrlForPrd(url)),
method: 'DELETE',
headers: {
'content-type': 'application/json; charse=UTF-8',
},
...config,
})
return this.handleSuccess(response, suppressErrorMessage)
} catch (e) {
this.handleError(e, suppressErrorMessage)
throw e
}
}
/**
* 上传文件
*/
public async uploadFile(
url: string,
file: File,
requestConfig: IRequestConfig = {}
): Promise {
const { suppressErrorMessage, ...config } = requestConfig
const formData = new FormData()
try {
formData.append('file', file)
const response: AxiosResponse = await axios.post(url, formData, {
headers: {
'content-type': 'multipart/form-data',
},
...config,
})
return this.handleSuccess(response, suppressErrorMessage)
} catch (e) {
this.handleError(e, suppressErrorMessage)
throw e
}
}
/**
* 处理请求成功
*/
private handleSuccess(response: AxiosResponse, suppressErrorMessage: boolean = false): T {
let message: string | undefined
switch (response.status) {
case 200:
break
case 400:
message = '请求参数错误!'
break
case 401:
message = '认证失败!'
break
case 403:
message = '没有访问权限!'
break
case 415:
message = '请求方式错误!'
break
default:
message = '未知状态错误!'
break
}
if (message && !suppressErrorMessage) {
this.errorHandler(response.status, message)
}
// tslint:disable-next-line: no-object-literal-type-assertion
return response.data || ({} as T)
}
/**
* 处理请求失败
*/
private handleError(error: AxiosError, suppressErrorMessage: boolean = false): void {
let status: number = 0
let message: string = '请求出错'
/* 构造错误消息 */
if (error.response) {
status = error.response.status
if (error.response.data.message) {
message = error.response.data.message
} else if (error.response.data.error) {
message = error.response.data.error
} else if (error.response.data.detail) {
message = error.response.data.detail
} else {
if (status === 404) {
message = error.message
} else {
message = error.response.data
}
}
} else if (error.request) {
status = error.request.status
message = error.request.responseText
} else {
message = error.message
}
if (!suppressErrorMessage) {
this.errorHandler(status, message)
}
}
/**
* 构造请求地址,添加时间戳参数,在开发环境禁用缓存
* @param url 请求地址
*/
private getUrlWithTimestamp(url: string): string {
return this.isProduction
? url
: `${url}${url.indexOf('?') > -1 ? '&' : '?'}_=${new Date().getTime()}`
}
}
export default new HttpClient(process.env.REACT_APP_ENV!.trim() === 'prd', defaultErrorHandler)