axios

217 阅读4分钟

axios

axios

  axios({
    url: 'https://httpbin.org/get',
    params: {
      name: 'zs',
      age: 15
    }
  }).then(res => {
    console.log(res);
  }).catch(err => {
    console.error(err)
  })

  axios({
    url: 'https://httpbin.org/post',
    data: {
      name: 'ls',
      age: 20
    },
    method: 'post'
  }).then(res => {
    console.log(res);
  }).catch(err => {
    console.error(err)
  })

request

axios.defaults.baseURL = 'http://123.207.32.32:8000'
axios.defaults.timeout = 5000
// axios.defaults.headers = {}

axios
  .request({
    url: '/home/multidata',
    method: 'GET'
  })
  .then((res) => {
    console.log(res)
  })

GET请求

get请求参数放到params中,也可以直接拼接,现在源码里面的params已经改为data了,所以使用paramsdata都行

axios
  .get(`/index/${this.keyWords}/${this.styleWords}/${this.rhyming}`)
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });
import axios from 'axios'

// axios为实例对象

axios
  .get('http://123.207.32.32:8000/home/multidata')
  .then((res) => {
    console.log(res.data)
  })
  .catch((err) => {
    console.log(err)
  })

axios
  .get('http://httpbin.org/get', {
    params: {
      name: 'zs',
      age: 18
    }
  })
  .then((res) => {
    console.log(res.data)
  })
  .catch((err) => {
    console.log(err)
  })

POST请求

post请求参数放到data

axios.post('http://httpbin.org/post', {
  data: {
    name: 'zs',
    age: 18
  }
})

直接发起请求

axios 也提供了类似于 jquery 中的 $.ajax() 的函数,如下:

<button id="btn3">直接使用axios发起GET请求</button>

 <script>
        document.querySelector('#btn3').addEventListener('click', function () {
            var url = 'http://www.liulongbin.top:3006/api/get'
            var paramsData = { name: '钢铁侠', age: 35 }
            axios({
                method: 'GET',
                url: url,
                params: paramsData
            }).then(function (res) {
                console.log(res.data);
            })
        })
    </script>

<button id="btn4">直接使用axios发起POST请求</button>

<script>
        document.querySelector('#btn4').addEventListener('click', function () {
            axios({
                method: 'POST',
                url: 'http://www.liulongbin.top:3006/api/post',
                data: {
                    name: '娃哈哈',
                    age: 18,
                    gender: '女'
                }
            }).then(function (res) {
                console.log(res.data);
            })
        })
    </script>

发起多个请求all

axios
  .all([
    axios.get('http://httpbin.org/get', { params: { name: 'zs', age: 18 } }),
    axios.post('http://httpbin.org/post', { data: { name: 'zs', age: 18 } })
  ])
  .then((res) => {
    console.log(res[0])
    console.log(res[1])
  })

axios.creact

在开发中,如果我们请求多台服务器的数据,那么baseURL可能就不一样了,这时候需要创建多个axios来请求多台服务器了

const instance1 = axios.create({
  baseURL: 'http://zs.org',
  timeout: 5000,
  headers: {

  }
})

const instance2 = axios.create({
  baseURL: 'http://ls.org',
  timeout: 3000,
  headers: {

  }
})

配置选项

全局配置

axios.defaults = "https://httpbin.org"
axios.defaults.timeout = 5000
// 给每个请求都加是token
axios.defaults.headers.common["token"] = "aaa"
// 给每个post请求添加token
axios.defaults.headers.post["token"] = "bbb"

baseURL

axios.defaults.baseURL = 'http://123.207.32.32:8000'

axios
  .get('/home/multidata')
  .then((res) => {
    console.log(res.data)
  })
  .catch((err) => {
    console.log(err)
  })

timeout

请求超时的时间

axios.defaults.timeout = 5000

headers

配置请求头

axios.defaults.headers = {}

单独配置

axios.defaults.baseURL = 'http://123.207.32.32:8000'

axios
  .get('/home/multidata', {
    timeout: 5000,
    headers: {}
  })
  .then((res) => {
    console.log(res.data)
  })
  .catch((err) => {
    console.log(err)
  })

拦截器

request的参数:

  • fn1:请求发生成功执行的函数
  • fn2:请求发送失败执行的函数

response的参数:

  • fn1:响应成功执行的函数
  • fn2:响应失败执行的函数
// 发送请求
axios.interceptors.request.use(fn1, fn2)
// 响应请求
axios.interceptors.response.use(fn1, fn2)

一般发送成功或者响应成功后被拦截做一些操作

axios.interceptors.request.use(
  (config) => {
    // 做一些操作
    // 1.添加token
    // 2.isLoading动画
    // 3.params/data序列化操作
    return config
  },
  (err) => {
    console.log('请求发送错误')
  }
)

axios.interceptors.response.use(
  (res) => {
    console.log('响应成功拦截')
    return res.data
  },
  (err) => {
    console.log('响应失败')
    if (err && err.response) {
        switch (err.response.status) {
          case 400:
            console.log('请求错误');
            break
          case 401:
            console.log('未授权操作');
            break
          default:
            console.log('其他错误信息');
        }
      }
    return err
  }
)

环境变量

第一种区分环境变量的方法:

service文件夹中创建request文件夹,在里面创建config.ts配置环境变量

let BASE_URL = ''
let BASE_NAME = ''
let TIME_OUT = 5000

if (process.env.NODE_ENV === 'development') {
  BASE_URL = 'http://zs.org/dev'
  BASE_NAME = 'zs1'
} else if (process.env.NODE_ENV === 'production') {
  BASE_URL = 'http://zs.org/prod'
  BASE_NAME = 'zs2'
} else {
  BASE_URL = 'http://zs.org/test'
  BASE_NAME = 'zs3'
}

export { BASE_URL, BASE_NAME, TIME_OUT }

第二种是在src平级中创建env文件

创建.env.development文件

VUE_APP_BASE_URL=https://zs.org/dev
VUE_APP_BASE_NAME=zs1

创建.env.production文件

VUE_APP_BASE_URL=https://zs.org/prod
VUE_APP_BASE_NAME=zs2

创建.env.test文件

VUE_APP_BASE_URL=https://zs.org/test
VUE_APP_BASE_NAME=zs3

封装axios

service文件夹中创建request文件夹,在里面创建config.ts配置环境变量

let BASE_URL = ''
const BASE_NAME = ''
const TIME_OUT = 5000

if (process.env.NODE_ENV === 'development') {
  BASE_URL = 'http://123.207.32.32:8000'
} else if (process.env.NODE_ENV === 'production') {
  BASE_URL = 'http://123.207.32.32:8000'
} else {
  BASE_URL = 'http://123.207.32.32:8000'
}

export { BASE_URL, BASE_NAME, TIME_OUT }

request中创建type.ts文件定义类型

import { AxiosRequestConfig, AxiosResponse } from 'axios'

export interface SXRequestInterceptors {
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorCatch?: (err: any) => any
  responseInterceptor?: (res: any) => any
  responseInterceptorCatch?: (err: any) => any
}

export interface SXRequestConfig extends AxiosRequestConfig {
  interceptors?: SXRequestInterceptors
  showLoading?: boolean
}

request中创建index.ts封装axios

import axios from 'axios'
// axios的实例类型与对于配置的类型
import type { AxiosInstance } from 'axios'
import { SXRequestInterceptors, SXRequestConfig } from './type'
import { ElLoading } from 'element-plus'

const DEFAULT_LOADING = true

class SXRequest {
  instance: AxiosInstance
  interceptors?: SXRequestInterceptors
  loading?: any
  showLoading: boolean

  constructor(config: SXRequestConfig) {
    // 创建axios实例
    this.instance = axios.create(config)

    // 保存基本信息
    this.interceptors = config.interceptors
    this.showLoading = config.showLoading ?? true

    // 使用拦截器
    // 1.从config中取出的拦截器是对于的实例的拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )

    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )

    // 2.添加所有实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        console.log('所有的实例都有的拦截器,请求成功拦截')
        if (this.showLoading) {
          this.loading = ElLoading.service({
            lock: true,
            text: 'Loading',
            background: 'rgba(0, 0, 0, 0.7)'
          })
        }
        return config
      },
      (err) => {
        console.log('所有的实例都有的拦截器,请求失败拦截')
        return err
      }
    )

    this.instance.interceptors.response.use(
      (res) => {
        console.log('所有的实例都有的拦截器,响应拦截成功')
        this.loading?.close()
        return res.data
      },
      (err) => {
        console.log('所有的实例都有的拦截器,响应拦截失败')
        return err
      }
    )
  }

  request<T>(config: SXRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      // 1.单个请求对请求config的处理
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors?.requestInterceptor(config)
      }

      // 2.判断是否需要显示loading
      if (config.showLoading === false) {
        this.showLoading = config.showLoading
      }

      this.instance
        .request<any, T>(config)
        .then((res) => {
          // 1.当请求的数据处理
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors?.responseInterceptor(res)
          }

          // 2.将showLoading设置为true 这样不会影响下一个请求
          this.showLoading = DEFAULT_LOADING

          // 3.将结果resolve返回出去
          resolve(res)
        })
        .catch((err) => {
          this.showLoading = DEFAULT_LOADING
          reject(err)
          return err
        })
    })
  }

  get<T>(config: SXRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }

  post<T>(config: SXRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }

  delete<T>(config: SXRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }

  patch<T>(config: SXRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }
}

export default SXRequest

service文件夹中index.ts引入

// service统一出口
import SXRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'

const sxRequest = new SXRequest({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  interceptors: {
    requestInterceptor: (config) => {
      console.log('请求拦截成功')
      return config
    },
    requestInterceptorCatch(err) {
      console.log('请求拦截失败')
      return err
    },
    responseInterceptor: (res) => {
      console.log('响应成功拦截')
      return res
    },
    responseInterceptorCatch(err) {
      console.log('响应失败拦截')
      return err
    }
  }
})

export default sxRequest

使用

import sxRequest from './service'

interface DataType {
  data: any
  returnCode: string
  success: boolean
}

sxRequest
  .request<DataType>({
    url: '/home/multidata',
    method: 'GET',
    showLoading: false
  })
  .then((res) => {
    console.log(res)
  })

代理

可以直接在vue.config.js中配置devSever代理

方式一与方式二的区别是:

// 方式一
axios.defaults.baseURL = '/api'

// 方式二
axios.defaults.baseURL = 'http://152.136.185.210:5000'
module.exports = {
  // 配置方式一:CLI提供的属性
  outputDir: './build',
  // publicPath: './',
  
  // 方式一
  devServer: {
    proxy: {
      '/api': {
        target: 'http://152.136.185.210:5000',
        pathRewrite: {
          '^/api': ''
        },
        changeOrigin: true
      }
    }
  },
  
  // 方式二
  devServer: {
    proxy: 'http://152.136.185.210:5000'
  },
}

也可以在configureWebpack中配置,会与webpack.config.js合并

module.exports = {
  configureWebpack: {
    // 方式一
    devServer: {
      proxy: {
        '/api': {
          target: 'http://152.136.185.210:5000',
          pathRewrite: {
            '^/api': ''
          },
          changeOrigin: true
        }
      }
    }
    
    // 方式二
    devServer: {
   	  proxy: 'http://152.136.185.210:5000'
  	},
  }
}