axios(非常全面)

目录

基本使用

常见请求方法

创建实例

常见请求配置

请求响应信息

默认配置

拦截器

取消请求

请求体编码

二次封装

封装原因

常见的可以做封装的部分

1.接口请求baseURL

2. 请求头与超时时间

3. 封装请求方法

4. 请求拦截器

5. 响应拦截器

跨域问题

vue-cli 2.x 版本

vue-cli 3.x 版本


基本使用

axios是一个基于pormise的网络请求库

注意事项 | Axios 中文文档 | Axios 中文网 (axios-http.cn)

常见请求方法

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

创建实例

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

常见请求配置

  • 请求地址:url: '/user'    必须有
  • 请求类型:method: 'get'   默认get 
  • 请根路径:baseURL: 'http://www.mt.com/api'
  • 请求前的数据处理:transformRequest:[function(data){}]
  • 请求后的数据处理: transformResponse: [function(data){}]
  • 自定义的请求头:headers:{'x-Requested-With':'XMLHttpRequest'}
  • URL查询对象:params:{ id: 12 },
  • 查询对象序列化函数:paramsSerializer: function(params){ }
  • request body:data: { key: 'aa'}
  • 超时设置:timeout: 1000,
  • 跨域是否带Token:withCredentials: false
  • 自定义请求处理:adapter: function(resolve, reject, config){}
  • 身份验证信息:auth: { uname: '', pwd: '12'}
  • 响应的数据格式json / blob /document /arraybuffer / text / stream:responseType: 'json'

请求响应信息

axios.get('/user/12345')
  .then(function (response) {
    console.log(response.data);   
    console.log(response.status);    //200 http状态码
    console.log(response.statusText);     //ok 状态信息
    console.log(response.headers);      //服务器响应头
    console.log(response.config);      //请求的配置信息
    //request 生成此响应的请求  node,js:最后一个ClientRequext实例    
                             // 浏览器:XMLHttpRequest实例
  });

默认配置

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

可重新赋值自定义

拦截器

请求或响应在then或catch之前进行拦截并添加相关操作

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });

移除

const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

错误处理

  • 请求成功,响应状态码,但是状态码超出2xx范围
  • 请求成功,响应不成功
  • 请求不成功
axios.get('/user/12345')
  .catch(function (error) {
    if (error.response) {
      // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // 请求已经成功发起,但没有收到响应
      // `error.request` 在浏览器中是 XMLHttpRequest 的实例,
      // 而在node.js中是 http.ClientRequest 的实例
      console.log(error.request);
    } else {
      // 发送请求时出了点问题
      console.log('Error', error.message);
    }
    console.log(error.config);
  });

自定义抛出错误的 HTTP code

axios.get('/user/12345', {
  validateStatus: function (status) {
    return status < 500; // 处理状态码小于500的情况
  }
})

获取更多关于HTTP错误的信息

axios.get('/user/12345')
  .catch(function (error) {
    console.log(error.toJSON());
  });

取消请求

请求体编码

暂时没用,先不写

二次封装

(1条消息) axios如何二次封装_axios的二次封装_gongshaoxu的博客-CSDN博客

封装原因

项目中涉及到的多个请求的配置很多都是相同的,如get请求,其他配置可能都相同,只有url不同。那相同部分代码就会造成冗余,通过二次封装,可以实现接口代码复用

axios('http://localhost:3000/data', {
  // 配置代码
  method: 'GET',
  timeout: 1000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'xxx',
  },
  transformRequest: [function (data, headers) {
    return data;
  }],
  // 其他请求配置...
})
.then((data) => {
  // todo: 真正业务逻辑代码
  console.log(data);
}, (err) => {
  // 错误处理代码  
  if (err.response.status === 401) {
  // handle authorization error
  }
  if (err.response.status === 403) {
  // handle server forbidden error
  }
  // 其他错误处理.....
  console.log(err);
});

常见的可以做封装的部分

1.接口请求baseURL

利用node环境变量来作判断,用来区分开发、测试、生产环境

if (process.env.NODE_ENV === 'development') {
  axios.defaults.baseURL = 'http://dev.xxx.com'
} else if (process.env.NODE_ENV === 'production') {
  axios.defaults.baseURL = 'http://prod.xxx.com'
}

在本地调试的时候,还需要在vue.config.js文件中配置devServer实现代理转发,从而实现跨域

2. 请求头与超时时间

一些具体的业务,需要携带一些参数

const service = axios.create({
    ...
    timeout: 30000,  // 请求 30s 超时
	  headers: {
        get: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
        },
        post: {
          'Content-Type': 'application/json;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
        }
  },
})

常见请求头

(1条消息) axios配置请求头content-type_axios设置content-type_Ideaing~的博客-CSDN博客

// 1 默认的格式请求体中的数据会以json字符串的形式发送到后端
  'Content-Type: application/json '
// 2 请求体中的数据会以普通表单形式(键值对)发送到后端
  'Content-Type: application/x-www-form-urlencoded'
// 3 它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
  'Content-Type: multipart/form-data'

1.默认

2.application/x-www-form-urlencoded'

3.Content-Type: multipart/form-data   应用:上传照片修改数据库中原始数据‘

let params = new FormData()
params.append('file', this.file)
params.append('qq', this.qq)
params.append('weChat', this.WeChat)
axios.post(URL, params, {headers: {'Content-Type': 'multipart/form-data'}}).then(res => {
          if (res.data.code === 0) {
                this.$router.go(-1)
          }
        }).catch(error => {
          alert('更新用户数据失败' + error)
        })

3. 封装请求方法

先引入封装好的方法,在要调用的接口重新封装成一个方法暴露出去

// get 请求
export function httpGet({
  url,
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
      params
    }).then((res) => {
      resolve(res.data)
    }).catch(err => {
      reject(err)
    })
  })
}

// post
// post请求
export function httpPost({
  url,
  data = {},
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios({
      url,
      method: 'post',
      transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {
          ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        return ret
      }],
      // 发送的数据
      data,
      // url参数
      params
    }).then(res => {
      resolve(res.data)
    })
  })
}

把封装的方法放在一个单独的js文件中(项目中用到的是service.js)

import { httpGet, httpPost } from './http'
export const getorglist = (params = {}) => httpGet({ url: 'apps/api/org/list', params })

页面中就能直接调用

// .vue
import { getorglist } from '@/assets/js/api'

getorglist({ id: 200 }).then(res => {
  console.log(res)
})

之后如果有大范围改动,直接改serviece.js即可

4. 请求拦截器

使用场景

  • 发送请求时添加‘正在加载中...’图标
  • 某些请求必须用户登陆,判断是否有用户token,没有跳转到登陆页
  • 对请求的参数进行序列化
axios.interceptors.request.use(
  config => {
    // 每次发送请求之前判断是否存在token
    // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况,此处token一般是用户完成登录后储存到localstorage里的
    token && (config.headers.Authorization = token)
    return config
  },
  error => {
    return Promise.error(error)
  })

5. 响应拦截器

使用场景:

  • 返回响应的res.data数据结果
  • 根据响应的status状态码,做出不同的操作。例如:如果status是401,响应拦截失败,那么通常是token失效,没有授权,要跳转至登陆页;status是200,响应拦截成功操作,返回res.data响应数据  如请求超时的话,就在这里进行处理,直接重新请求,还是发送给用户信息请求
axios.interceptors.response.use(response => {
  // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
  // 否则的话抛出错误
  if (response.status === 200) {
    if (response.data.code === 511) {
      // 未授权调取授权接口
    } else if (response.data.code === 510) {
      // 未登录跳转登录页
    } else {
      return Promise.resolve(response)
    }
  } else {
    return Promise.reject(response)
  }
}, error => {
  // 我们可以在这里对异常状态作统一处理
  if (error.response.status) {
    // 处理请求失败的情况
    // 对不同返回码对相应处理
    return Promise.reject(error.response)
  }
})

跨域问题

跨域本质上是同源策略引起的(主机名、域名、端口需要保持一致)

方向是:前端/后端

后端:中间件/服务端进行跨域相关配置,在项目中新建允许跨域配置类

axios实现跨域三种方法_cors跨域axios - 腾讯云开发者社区-腾讯云 (tencent.com)

这里主要介绍前端的跨域解决方案,都是做配置项,实现代理转发

vue-cli 2.x 版本

  • Vue 的 config-> index.js 中,在 proxyTable 对象中书写跨域配置项:
  • 将以 /api 开头的请求地址基础URL替换为 请求的第三方接口
    dev: {
        env: require('./dev.env'),
        port: 8889,
        autoOpenBrowser: true,
        assetsSubDirectory: 'static',
        assetsPublicPath: '/',
        proxyTable: {
           //axios跨域改造 by zhengkai.blog.csdn.net
          '/api': {
            target:'http://localhost:8888/cert/', // 请求的第三方接口
            changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
            pathRewrite:{  // 路径重写,
              '^/api': ''  // 替换target中的请求地址,也就是说/api=/target,请求target这个地址的时候直接写成/api即可。
            }
          }
        },
        // CSS Sourcemaps off by default because relative paths are "buggy"
        // with this option, according to the CSS-Loader README
        // (https://github.com/webpack/css-loader#sourcemaps)
        // In our experience, they generally work as expected,
        // just be aware of this issue when enabling this option.
        cssSourceMap: false
      }
  • 将 axios 的 baseURL 改为 /api
    //引入axios  by zhengkai.blog.csdn.net
    import axios from 'axios'
    Vue.prototype.$axios = axios
    axios.defaults.baseURL = '/api'  //自动附加在所有axios请求前面,则可以省略/api,直接写'/xxxx/xxx'。否则需要设置'/api/xxxx/xxx'
    

vue-cli 3.x 版本

  • 根目录创建全局配置文件vue.config.js,在proxy中作跨域配置(devServer是webpack配置)
  • 将 axios 的 baseURL 改为 /proxyApi
devServer: {
    proxy: {
      '/proxyApi': {
        target: 'http://dev.xxx.com',
        changeOrigin: true,
        pathRewrite: {
          '/proxyApi': ''
        }
      }
    }
  }

疑问:axios本身就是promise,为什么在进行封装请求方法的时候还要在外面加一层promise

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值