axios 结合 vue typescript 二次封装

axios 中文文档

下载

$ npm install axios

使用

import axios from 'axios'

async function getUserList (){
 const result = await axios.get('http://localhost:3000/api/users')
}

参数

与请求一起发送的 URL 参数

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
}

你可能感兴趣的:(vue,typescript,typescript,vue.js,ajax)