# AXIOS

# 一、网络请求模块的选择

# 1】模块选择
# ①选择一:传统的Ajax是基于XMLHTTPRequest(XHR)

为什么不选择它?

  • 配置和调用方式等非常混乱
  • 编码起来看起来很蛋疼
  • 所以真实开发中很少直接使用,而是使用jQuery-Ajax
# ②选择二:在前面的学习中,我们经常会使用jQuery-Ajax
  • 相对于传统的Ajax非常好用

为什么不选择它?

  • 首先,我们先明确一点:在Vue的整个开发中都是不需要使用jQuery了
  • 那么,就意味着为了方便我们进行一个网络请求,特意引用一个jQuery
  • 完全没必要为了用网络请求就引用这个重量级框架
# ③选择三:官方在Vue1.x的时候,推出了Vue-resource
  • Vue-resource的体积相对于jQuery小很多
  • 另外Vue-resource是官方推出的

为什么不选择它?

  • 在Vue2.0推出之后,Vue作者就在GitHub的Issues中说明了去掉Vue-resource,并且以后不再更新
  • 那么意味着Vue-resource不再支持新的版本,也不再继续更新维护。对以后的项目开发和维护都存在很大的隐患
# ④选择四:axios框架

axios有很多的有点,并且用起来也非常方便

为什么选择axios:

  • 在浏览器中发送XMLHTTPRequests请求
  • 在node.js中发送http请求
  • 支持Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 等等
# 2】jsonp网络请求方式

在前端开发中,我们一种常见的网络请求方式就是jsonp

  • 使用jsonp最主要的原因往往是为了解决跨域访问的问题

jsonp的原理是:

  • jsonp的核心在于通过<script>标签在src来帮助我们请求数据
  • 原因是我们的项目部署在domain1.com服务器上时。是不能直接访问domain2.com服务器上的资料的
  • 这个时候,我们利用<script>标签的src帮助我们去服务器请求到数据,将数据当做一个JavaScript的函数来执行,并且执行的过程中传入我们需要的json
  • 所以,封装jsonp的核心就在于我们监听window上的jsonp进行回调时的名称

# 二、axios框架的基本使用

# 1】安装axios
npm install axios --save
# 2】axios的多种用法
  • axios({config})
  • axios.request({config})
  • axios.get(url [,config])
  • axios.delete(url [,config])
  • axios.head(url [,config])
  • axios.post(url [,data [,config] ])
  • axios.put(url [,data [,config] ])
  • axios.patch(url [,data [,config] ])
# 3】具体实现代码:

注意这里axios不需要new,直接使用该方法即可

在axios框架中也是使用了**.then()**来获得结果->说明是使用了Promise

import Vue from 'vue'
import App from './App'
import axios from 'axios'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  render: h => h(App)
})
//方式一
axios({
  url:'http://123.207.32.32:8000/home/multidata',
  //method:'post'
    //默认使用get
}).then(res=>{
  console.log(res)
})
//方式二
axios({
  url:"http://123.207.32.32:8000/home/data?type=pop&page=1",
    //使用get请求
}).then(res=>{
  console.log(res)
})
//和上面方式二是相同的
axios({
  url:"http://123.207.32.32:8000/home/data",
  //专门针对get请求的参数拼接
  params:{
    type:'pop',
    page:1
  }
}).then(res=>{
  console.log(res)
})

# 三、axios.all()发送并发请求

使用**axios.all()方法,和ES6中的promise.all()**方法差不多

  • 有时候我们可能需求同时发送两个请求
    • 使用axios.all(),可以放入多个请求的数组
    • axios.all([axios(),...,axios()])返回的结果是一个数组,使用axios.spread()可将数组[res1,...,res2]展开为res1,...,res2
# 具体代码实现:
axios.all([axios({
  url:'http://123.207.32.32:8000/home/multidata'
}),axios({
  url:"http://123.207.32.32:8000/home/data",
  params:{
    type:'pop',
    page:1
  }}
)]).then(axios.spread((res1,res2)=>{
  console.log(res1);
  console.log(res2);
}))
//.then(res=>{console.log(res)})
# es6解构赋值
//es6语法解构赋值
//对象解构:
const obj={
    name:'kobe',
    age:30
}
const {name,age} = obj;

//数组解构:
const names=['why','kobe','james'];
//const name1=names[1]
//const name2=names[2]
//const name3=names[3]
const[name1,name2,name3] = names;

# 四、axios的全局配置

  • 事实上,在开发中可能很多参数都是固定的,比如BaseURL是固定的
  • 这个时候我们可以进行一些抽取,也可以利用axios的全局配置
    • 使用axios.defaults属性
axios.defaults.baseURL = '123.207.32.32:8000'
axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded'

# 五、常见的axios配置选项

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

# 六、axios的实例

# 1】为什么要创建axios的实例?
  • 当我们从axios模块中导入对象时,使用的实例是默认的实例
  • 当给该实例设置一些默认配置时,这些配置就被固定下来了
  • 但是后续开发中,某些配置可能会不太一样
  • 比如某些请求需要使用特定的baseURL或者timeout或者content-Type等
  • 这时候,我们就可以创建新的实例,并且传入属于该实例的配置信息
# 2】使用axios.create()方法

有时候不使用全局的axios配置时,我们就需要创建axios实例。

const instance1=axios.create({
  baseURL:'http://123.207.32.32:8000',
  timeout:5000
})
instance1({
  url:'home/multidata'
}).then(res=>{
  console.log(res);
})
instance1({
  url:'home/data',
  params:{
    type:'pop',
    page:1
  }
}).then(res=>{
  console.log(res);
})

# 七、axios的模块封装

# 1】通过增加函数型参数(回调函数)
# src/network/request.js
import axios from 'axios'

export function request(config,success,failure){
    //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    })
    //发送真正网络请求
    instance(config).then(res=>{
        success(res)
    }).catch(err=>{
        failure(err)
    })
}
# main.js
//5.封装request模块
import {request} from './network/request'

request({
  url:'/home/multidata'
},res=>{
  console.log(res);
},err=>{
  console.log(err);
})
# 2】把传入的唯一参数当成对象来处理(对象中设置回调函数)
# src/network/request.js
import axios from 'axios'

export function request(config){
    //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    })
    //发送真正网络请求
    instance(config.baseConfig).then(res=>{
        config.success(res)
    }).catch(err=>{
        config.failure(err)
    })
}
# main.js
import {request} from './network/request'

request({
  baseConfig:{url:'/home/multidata'},
  success(res){
    console.log(res);
  },
  failure(err){
    console.log(err);
  }
})
# 3】使用ES6语法的Promise
# src/network/request.js
import axios from 'axios'
//方式三
export function request(config){
    //包装一个Promise
    return new Promise((resolve,reject)=>{
        //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    })

        //发送真正网络请求
    instance(config).then(res=>{//这个then是在获取结果
        resolve(res)//此时这个resolve是需要在Promise()对象后面.then进行处理
    }).catch(err=>{
        reject(err)
    })
})
}
# main.js
import {request} from './network/request'

request({
  url:'/home/multidata'
}).then(res=>{
  console.log(res);
}).catch(err=>{
  console.log(err)
})
# 4】axios实例的返回类型本来就是Promise类型,不需要再次包装一次(最终推荐)
# src/network/request.js
import axios from 'axios'
//方式四
export function request(config){
        //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    })
        //发送真正网络请求
    return instance(config)
    //直接return instance,因为他axios实例的返回值本身就是Promise类型
    //所以不需要再return new Promise()
}
# main.js
import {request} from './network/request'

request({
  url:'/home/multidata'
}).then(res=>{
  console.log(res);
}).catch(err=>{
  console.log(err)
})

# 八、axios拦截器的使用

  • axios提供了拦截器,用于我们在发送每次请求或者得到响应后,进行相应的处理
# 1】axios的请求拦截
import axios from 'axios'
export function request(config){
        //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    })
        //2.axios的请求拦截
        instance.interceptors.request.use(config=>{
            console.log(config);//请求发送成功就会进入use的第一个参数
            //在拦截到请求之后,①可以对请求的信息进行修改 
            //②希望在发送请求之后界面出现请求图标向用户显示
            //③某些网络请求(比如登陆携带token),必须携带一些特殊的信息
            ...
            return config// 返回一个config,否则发出的请求被拦截,正常返回的结果拿不到,所以必须要return一个config
        },err=>{
            console.log(err);
        })
        //3.发送真正网络请求
    return instance(config)
    //直接return instance,因为他axios实例的返回值本身就是Promise类型
}
# 2】axios的响应拦截
import axios from 'axios'
export function request(config){
        //1.创建axios的实例
    const instance = axios.create({
        baseURL:'http://123.207.32.32:8000',
        timeout:5000
    }) 
        //2.axios的响应拦截
        instance.interceptors.response.use(res=>{
            console.log(res);
            return res.data;//也必须要返回响应拦截之后的结果,否则axios正常响应的结果main.js中拿不到
        },err=>{
            console.log(err);
        })
        //3.发送真正网络请求
    return instance(config)
    //直接return instance,因为他axios实例的返回值本身就是Promise类型
}

[客户端]----发送请求(请求拦截)---->[服务器]----响应结果(响应拦截)---->[客户端]

Last Updated: 7/15/2020, 10:34:45 PM