Vue axios基础
基于 promise 的 HTTP 客户端axios
axios本身具有以下特征:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防止 CSRF/XSRF
Promise
Promise 是异步编程的一种解决方案,而且还是以一种优雅的方式来处理异步请求的,本质上是一个构造函数,函数本身上巨有all、reject、resolve这几个方法,原型上有then、catch等方法。
对于主要解决的问题,由于笔者至今还未遇到过这样的需求,所以感触并没有太深刻,但是可以简单说明一下:
比如说对于传统的Ajax请求,如果第一次通过url1发送请求的时候需要服务器返回一个数据data1,而我们又需要data1取出url2的地址,来进行第二次网络请求,同理,第三次网络请求又需要第二次网络请求的返回的数据data2取出的url3… 这样一层层下去,不仅仅需要先验判断某一层网络请求失败的情况的代码,而且我们不能很好地将数据处理和数据请求分离,这样的代码就会显得很是冗余,一旦出现bug,对开发人员的debug要求就会变得很高。
其大致用法如下:
// 第一次异步网络请求
new Promise((resolve,reject) => {
// 异步通信数据请求代码
resolve(val) // 请求成功调用此函数
reject(err) // 请求失败调用此函数
}).then(val => {
// 处理第一次成功请求
// 第二次异步网络请求
new Promise((resolve,reject) => {
// 异步通信数据请求代码
resolve(val) // 请求成功调用此函数
reject(err) // 请求失败调用此函数
}).then(val => {
...
}).catch(err => {
...
})
}).catch(err => {
// 处理第一次失败请求
})
axios的基本使用
项目根目录下执行以下命令安装axios:
npm install axios --save
导入并使用axios:
import axios from 'axios'
// get方式
axios({
url: "http://httpbin.org/get",
method: 'get',
params:{
name: "张三",
id: 1001,
age: 21
}
}).then(res => {
console.log(res);
})
// post方式
axios({
url: "http://httpbin.org/post",
method: 'post',
data:{
name: "张三",
id: 1000,
age: 20
}
}).then(res => {
console.log(res);
})
结果显示:
axios的并发请求
有时候,我们需要满足这样的需求:必须在特定的一些网络请求全部成功后才能统一执行某一事件。而axios已经封装好了这个方法,如下演示:
import axios from 'axios'
axios.all([
axios({
method: "get",
url: "http://httpbin.org/get",
params:{
name:"张三",
id: 1001
}
}).then(res => {
console.log("第一个axios请求成功",res);
return res;
}),
axios({
method: "post",
url: "http://httpbin.org/post",
data: {
name:"李四",
id: 1002
}
}).then(res => {
console.log("第二个axios请求成功",res);
return res;
}),
axios({
method: "post",
url: "http://httpbin.org/post",
data: {
name:"王五",
id: 1003
}
}).then(res => {
console.log("第三个axios请求成功",res);
return res;
})
]).then(result => {
console.log("这个一定是等待以上全部请求成功后… ",result[0],result[1],result[2]);
})
为了减少相关代码的重复冗余,选择公共默认选项,可以使用axios.defaults方法,如下演示:
axios.defaults.baseURL = "http://httpbin.org";
axios.defaults.timeout = 1000; // 超时限制
axios({
url: "/get",
method: 'get',
params:{
name: "张三",
id: 1001,
age: 21
}
}).then(res => {
console.log(res);
})
axios({
url: "/post",
method: 'post',
data:{
name: "张三",
id: 1000,
age: 20
}
}).then(res => {
console.log(res);
})
axios实例化
对于一些分布式服务器来说,全局配置axios可能是会冲突的,因此,axios允许创建axios实例。
const request1 = axios.create({
baseURL: "http://httpbin.org",
timeout: 1000
})
const request2 = axios.create({
baseURL:"http://httpbin.org",
timeout: 2000,
method: "post"
})
request1({
url: "/get",
params:{
name:"张三",
age: 20
}
}).then(res => {
console.log(res);
})
request2({
url: "/post",
data:{
name:"李四",
age: 21
}
}).then(res => {
console.log(res);
})
axios模块化
为了减少网页之间与axios之间的耦合度(解耦合),可以通过一个文件作为全局索引导入。
如,可以在src目录下创建一个network文件夹,目录下再创建request.js:
import axios from 'axios'
// 这里config作为配置参数,success作为成功回调函数,failure作为失败回调函数
export function request(config,success,failure){
const instance = axios.create({
baseURL: "http://httpbin.org",
timeout: 2000
})
// 发送真正的网络请求
instance(config).then(res => {
success(res)
}).catch(err => {
failure(err)
})
}
使用方式:
import {request} from './network/request'
request({
url: "get",
method: 'get',
params: {
name: "张三",
age: 20
}
}, res => {
console.log(res);
}, err => {
console.log(err);
})
request({
url: "post",
method: 'post',
data: {
name: "王五",
age: 21
}
}, res => {
console.log(res);
}, err => {
console.log(err);
})
上例解释,创建一个axios实例,实现多组件共享,通过传递成功请求回调函数和传递失败回调函数作为一个出口,用户通过传递config参数也能自定义配置。同样,读者也可以实现多个axios默认实例导出供多个组件共享。
以上版本可以进一步升级,通过Promise方式,即进一步封装增强Promise:
request.js:
export function request(config){
return new Promise((resolve,reject) => {
// 配置默认项
const instance = axios.create({
baseURL: "http://httpbin.org",
timeout: 2000
})
// 发送网络请求
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
使用方式:
import {request} from './network/request'
request({
url: "/get",
method: 'get',
params:{
name: "张三",
age: 20
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
request({
url: "/post",
method: 'post',
params:{
name: "赵六",
age: 21
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
再进一步升级简化:
export function request(config){
const instance = axios.create({
baseURL: "http://httpbin.org",
timeout: 2000
})
// 发送真正的网络请求
return instance(config);
}
之所以可以像上面一样可以直接返回axios实例,是因为其本身就是继承了Promise。
拦截器
对于请求成功或失败,相应成功或失败都可以进行相应拦截操作。
一般可用作网络加载页面图标显示,或者登录页面的token验证等…
request.js:
export function request(config){
const instance = axios.create({
baseURL: "http://httpbin.org",
timeout: 2000
})
instance.interceptors.request.use(config => {
console.log("请求拦截配置:",config);
return config;
},err => {
console.log(err);
})
instance.interceptors.response.use(res => {
console.log("响应拦截结果:",res);
return res.data.args; // 返回data即可
},err => {
console.log(err);
})
// 发送真正的网络请求
return instance(config);
}
使用:
import {request} from './network/request'
request({
url: "/get",
method: 'get',
params:{
name: "张三",
age: 20
}
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})