axios网络请求模块
常见的网络请求模块及优缺点对比:
JSONP的原理和封装
- JSONP原理回顾
- JSONP请求封装
axios的内容详解
- 认识axios网络模块
- 发送基本请求
- axios创建实例
- axios拦截器的作用
Vue中发送网络请求有非常多的方式,在开发中如何选择?
选择一:传统的Ajax是基于XMLHttpRequest(XHR)
为什么不用它?
配置和调用方式非常混乱,编码看起来不简洁,真是开发中常使用jQuery-Ajax。
在前端开发中,我们一种常见的网络请求方式就是JSONP
使用JSONP最主要的原因往往是为了解决跨域访问的问题。
JSONP的原理是什么呢?
- JSONP的核心在于通过script标签的src来帮助我们请求数据;
- 原因是我们的项目部署在domain1.com服务器上时,是不能直接访问domain2.com服务器上的资料的;
- 这个时候,我们利用script标签的src帮助我们去服务器请求到数据,将数据当作一个javascript的函数来执行,并且执行的过程中传入我们需要的json;
- 所以,封装jsonp的核心就在于我们监听window上的jsonp进行回调时的名称;
axios功能特点:
- 在浏览器中发送XMLHttpRequests请求;
- 在Node.js中发送http请求;
- 支持Promise API;
- 拦截请求和响应;
- 转换请求和响应数据
- 等等
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[, coonfig]])
axios.patch(url[, data[, config]])
axios在项目中具体执行过程
此处例子,在App.vue里发送网络请求,并且从服务器获取请求过来的数据,之后对数据进行相关的展示。
在项目中具体使用axios
首先安装axios:
npm install axios --save
之后在main.js中使用,基础用法:(也可以在App.vue中使用)
import axios from 'axios'
axios({
//示例接口
url: 'httpbin.org/' //模拟网络请求,进行网络模块封装时,用这个网站对网络测试
//项目中使用的接口url,真实数据。请求123.207.32.32:8000下的8000端口下的home下的multidata
url: 'http://123.207.32.32:8000/home/multidata' //向服务器请求数据
}).then(res => { //返回请求数据的结果
console.log(res)
})
axios({
url: 'http://123.207.32.32:8000/home/data'
//当不想在url中内容写太长时,可以写在params中,会自动拼接到url对应位置
//params专门针对get请求的参数拼接
params: {
type: 'pop',
page: 1
}
}).then(res => {
console.log(res)
})
第二种用法:有时候可能需要同时发送两个请求
-
使用axios.all,可以放入多个请求的数组;
-
axios.all([])返回的结果是一个数组,使用axios.spread可将数组[res1,res2]展开为res1,res2。
当做一个功能同时需要发送两个请求,且两个请求必须同时到达后才能往下写对应功能,解决方法一是用promise.all。
//axios发送并发请求
axios.all([axios(), axios()]).then(results => {})
//具体实例:
axios.all([
axios([
url: 'http://123.207.32.32:8000/home/multidata'
]),
axios([
url: 'http://123.207.32.32:8000/home/data',
params: {
type: 'sell',
page: 5,
}
])
]).then(results => { //两个url请求统一在这处理
console.log(results) //如果想把结果分开,用spread
})
------------------>使用spread
axios.all([
axios([
url: 'http://123.207.32.32:8000/home/multidata'
]),
axios([
url: 'http://123.207.32.32:8000/home/data',
params: {
type: 'sell',
page: 5,
}
])]).then(axios.spread(res1, res2 => {
console.log(res1)
console.log(res2)
})
})
第三种用法:全局配置
在上面的示例中,我们的baseURL是固定的
- 事实上,在开发中可能很多参数都是固定的;
- 这个时候我们可以进行一些抽取,也可以利用axiox的全局配置
axios.defaults.baseURL = '123.207.32.32:8000'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
axios.defaults.baseURL = 'http://123.207.32.32:8000' //把基础url单独设置出来,此时为全局配置
axios.defaults.timeout = 5000 //设置超时时间为5秒
//此时axios请求可以改写为
axios.all([
axios({
url: '/home/multidata'
}),
axios({
url: '/home/data',
params: {
type: 'sell',
page: 5,
}
})
]).then(axios.spread((res1, res2) => {
console.log(res1)
console.log(res2)
})
)
//执行结果:两次请求
//{data: {…}, status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
//{data: {…}, status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
常见的配置选项
请求地址:
url: '/user'
请求类型
method: 'get' //默认请求为get,后接params,如果为post后面能接请求体body,当为get时不能接body请求体,post同理
请根路径
baseURL: 'http://123.207.32.32:8000'
请求前的数据处理
transformRequest:[function(data){}]
请求后的数据处理
transformResponse:[function(data){}]
自定义的请求头
headers:{'x-Requested-With':'XMLHttpRequest'}
URL查询对象
params:{id: 12}
请求体request body
data:{key:'aa'}
axios的实例
为什么要创建axios的实例?
当我们从axios模块中导入对象时,使用的实例是默认的实例,当给该实例设置一些默认配置时,这些配置就被固定下来了,但是后续开发中,某些配置可能会不太一样,比如某些请求需要使用特定的baseURL或者timeout或者content-Type等,这个时候,可以创建新的实例,并且传入属于该实例的配置信息。
(使用实例也就不是全局配置了)
//创建对应的axios实例,实例名称为instance1
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)
})
//实例不只一个,创建实例2,instance2
const instance2 = axios.create({
baseURL: 'http://123.207.32.32:8000'
timeout: 5000
})
axiso实例封装
(在哪使用在哪导入的方式不利于维护,得具体到每个使用点一个一个修改,所以要封装后再使用)封装后组件请求网络时只需请求这一个文件。
(第三方框架最好不要直接使用,封装后使用较好)
比如在目录里创建network文件,然后创建request.js文件把请求网络axios写在这里面,最后再在页面中引用。
若创建多个访问实例,则不用export default xx语句,因为导出的不只一个名字不同,
所以用export function instance1() {};export function instance2() {}等,本次起名叫request即export function request(){}。
方式一:
在request.js文件中创建请求
import axios from 'axios'
//封装request网络请求模块,可以方便在别处调用该模块,传入三个参数config,success,failure其中后两个是函数
export function request(config, success, failure) {
//1.创建axios的实例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.发送真正的网络请求。将传来的config传入到实例里才能进行真正的网络请求,之后还需要把结果给调用者传出去,也可能会出现异常且也得传出去,所以也得考虑.then和.catch回调出去,所以在开始封装时传入两个函数success和failure,则这两个函数可以传参数res和err,也即是success(res)和failure(err)语句。
instance(config)
.then(res => {
//console.log(err)
success(res)
})
.catch(err => {
//console.log(err)
failure(err)
})
}
在main.js文件中使用请求
//3.封装request模块
import {request} from './network/request'
//调用request
request({
//调用时传入config
url: '/home/multidata'
}, res => {
//此处res是success(res)中的res
console.log(res)
}, err => {
//此处err是failure(err)中的err
console.log(err)
})
方式二:
跟promise结合的方式
//创建
import axios from 'axios'
export function request(config) {
return new Promise((resolve, reject) => {
//1.创建axios的实例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
})
//发送真正的网络请求
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
}
//调用
import {request} from './network/request'
request({
url: '/home/multidata'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
方式三:
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)
}
//调用
import {request} from './network/request'
request({
url: '/home/multidata'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
axios拦截器
(补充知识点:把函数作为参数传到另一个函数里调用即为回调函数)
拦截器用于我们在发送每次请求或者得到相应数据后进行对应的处理。
如何使用拦截器?(interceptors)
接着使用上面的axios例子
instance.interceptors.request //全局拦截instance的request请求
instance.interceptors.response //全局拦截instance的response响应
实例:请求拦截
instance.interceptors.request.use(config => {
console.log(config)
//拦截后需要返回config参数要不然没数据,调用时会被catch捕捉到报错
return config
}, err => {
console.log(err)
})
//调用
request({
url: '/home/multidata'
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
请求拦截的作用:
1.比如config中的一些信息不符合服务器的要求;
2.比如每次发送网络请求时,都希望在界面中显示一个请求的图标;
3.某些网络请求(比如登录(token)),必须携带一些特殊的信息;
实例:响应拦截(拿到的是结果故参数为res)
instance.interceptors.response.use(res => {
console.log(res);
//此处返回结果因为只用得到data所以只需返回data就行
return res.data
}, err => {
console.log(err)
})
//调用
request({
url: '/home/multidata'
}).then(res => {
//响应拦截只返回data后,此处打印的结果就只剩data里的内容
console.log(res)
}).catch(err => {
//console.log(err)
})
(如有问题请指正)