axios 中文文档
$ npm install axios
import axios from 'axios'
async function getUserList (){
const result = await axios.get('http://localhost:3000/api/users')
}
query 参数
// 写法一
async function getUserList() {
const result = await axios.get('http://localhost:3000/api/users?page=1&limit=10')
}
// 写法二
async function getUserList() {
const result = await axios.get('http://localhost:3000/api/users', {
params: {
page: 1,
limit: 10
}
})
}
params 参数
async function findUser() {
const result = await axios.get('http://localhost:3000/api/user/2')
}
JSON (application/json)
async function createUser() {
const result = await axios.post('http://localhost:3000/api/user', {
name: '张三',
age: 20
})
}
URL encoded form (application/x-www-form-urlencoded)
async function createUser() {
const result = await axios.post('http://localhost:3000/api/user', 'name=张三&age=20')
}
默认情况下,axios将 JavaScript 对象序列化为 JSON 。 要以application/x-www-form-urlencoded格式发送数据,可以使用 qs
$ npm install qs
import qs from 'qs'
const data = {
name: '张三',
age: 20
}
async function createUser() {
const result = await axios.post('http://localhost:3000/api/user', qs.stringify(data),{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
Multipart / FormData (multipart/form-data)
<input type="file" placeholder="请选择" @change="handleChange" />
async function handleChange(e: Event) {
const { files } = e.target as HTMLInputElement
if (files && files.length) {
const formData = new FormData()
formData.append('file', files[0])
formData.append('字段', '值')
await axios.post('http://localhost:3000/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
}
src/utils/request/helpers.ts
export function handleAxiosError(axiosError: any) {
// 默认值
const error = {
code: 'ERR_BAD_RESPONSE',
status: 500,
message: '请求错误'
}
/** 2xx 范围的错误处理 */
if (axiosError?.data) {
const { status } = axiosError
const { code, msg: message } = axiosError.data
Object.assign(error, { code, status, message })
}
/** 超出 2xx 范围的错误处理 */
if (axiosError?.response) {
const { code, message, status } = axiosError.response.data
Object.assign(error, { code, status, message })
}
console.log('统一处理 error : ', error)
}
src/utils/request/index.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import qs from 'qs'
import { handleAxiosError } from './helpers'
/** 白名单 无需加 Authorization */
const white_list = ['/login']
/** 存放请求 */
const pendingMap = new Map()
/** 拼接请求的key */
function getRequestKey(config: AxiosRequestConfig) {
return (config.method || '') + config.url + '?' + qs.stringify(config?.data)
}
/** 处理 */
function setPendingMap(config: AxiosRequestConfig) {
const key = getRequestKey(config)
if (pendingMap.has(key)) {
pendingMap.get(key).abort()
pendingMap.delete(key)
}
const controller = new AbortController()
pendingMap.set(key, controller)
config.signal = controller.signal
}
/** axios 实例 */
const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_API,
timeout: 10 * 1000,
headers: { 'Content-Type': 'application/json' }
})
// 添加请求拦截器
instance.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
/** 不在白名单里,加上 Authorization */
if (config?.url && !white_list.includes(config.url)) {
const token = localStorage.getItem('token') || ''
config.headers.Authorization = `Bearer ${token}`
}
/** 取消重复请求 */
if (!config.repeatRequest) {
setPendingMap(config)
}
return config
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse<Global.BackendResponse>) => {
// 2xx 范围内的状态码都会触发该函数。
const key = getRequestKey(response.config)
if (pendingMap.has(key)) {
pendingMap.delete(key)
}
if (response.data.code === 0) {
/** 成功 */
return response
} else {
/** 失败 */
handleAxiosError(response)
return Promise.reject(response)
}
},
(error) => {
/** 超出 2xx 范围的状态码都会触发该函数。 */
/** 取消请求 */
if (axios.isCancel(error)) {
console.log('请求取消', error)
}
handleAxiosError(error)
return new Promise(() => {})
}
)
export default instance
src/api/user/index.ts
import instance from '@/utils/request'
export const usersApi = async () => {
const result = await instance.get<Global.BackendResponse<Array<ApiUser.UserInfo>>>('/users', {})
return result.data
}