Axios学习

选择什么网络模块?

Ajax

选择一: 传统的Ajax是基于XMLHttpRequest(XHR)

为什么不用它呢?

  • 非常好解释, 配置和调用方式等非常混乱.
  • 编码起来看起来就非常蛋疼.
  • 所以真实开发中很少直接使用, 而是使用jQuery-Ajax

jQuery-Ajax

选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax

  • 相对于传统的Ajax非常好用.

为什么不选择它呢?

  • 首先, 我们先明确一点: 在Vue的整个开发中都是不需要使用jQuery了.
  • 那么, 就意味着为了方便我们进行一个网络请求, 特意引用一个jQuery, 你觉得合理吗?
  • jQuery的代码1w+行.
  • Vue的代码才1w+行.
  • 完全没有必要为了用网络请求就引用这个重量级的框架.

Vue-resource

选择三: 官方在Vue1.x的时候, 推出了Vue-resource.

  • Vue-resource的体积相对于jQuery小很多.
  • 另外Vue-resource是官方推出的.

为什么不选择它呢?

  • 在Vue2.0退出后, Vue作者就在GitHub的Issues中说明了去掉vue-resource, 并且以后也不会再更新.
  • 那么意味着以后vue-reource不再支持新的版本时, 也不会再继续更新和维护.
  • 对以后的项目开发和维护都存在很大的隐患.

Axios

Vue作者推荐,axios有非常多的优点, 并且用起来也非常方便.

特性

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

axiox请求方式

  • 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]])

axios的基本使用

  • 安装

    1
    npm install axios --save
  • 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //导入 axios
    import axios from "axios"

    axios({
    // url 是用于请求的服务器 URL
    url: "http://123.207.32.32:8000/home/multidata",
    // method 是创建请求时使用的方法
    //不写type默认为get请求
    type: "get"
    }).then((res) => {
    console.log(res)
    })

    20200711175552.png

  • get请求参数拼接 params 是即将与请求一起发送的 URL 参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //导入 axios
    import axios from "axios"

    axios({
    //不使用 params 可以直接拼接 http://123.207.32.32:8000/home/data?type=pop&page=3
    url: "http://123.207.32.32:8000/home/data",
    type: "get",
    params:{
    type: 'pop',
    page :1
    }
    }).then((res) => {
    console.log(res)
    })

    常见请求的参数

  • Get请求

    axios.get(url, params).then(res => { do something })

    例子:

    1
    2
    3
    4
    5
    axios.get("xxx", {
    params :{
    id: 1
    }
    }).then(res => { consloe.log(res.data) })
  • Post请求

    axios.post(url, data).then(res => { do something })

    1
    axios.get("xxx", this.form).then(res => { consloe.log(res.data) })

    axios的并发请求

当想同时请求多个地址时、就需要使用axios.all(iterable) 类似: axios.all([axios({}),axios({}),...]).then()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//导入 axios
import axios from "axios"

axios.all([axios({
url: "http://123.207.32.32:8000/home/multidata",
type: "get"
}), axios({
url: "http://123.207.32.32:8000/home/data",
type: "get",
params: {
type: 'pop',
page: 1
}
})]).then((results) => {
//打印的是一个数组对象
console.log(results)
})

20200711203105.png

使用 axios.spread 可将数组 [res1,res2] 展开为 res1, res2

1
2
3
4
5
6
7
8
9
10
11
12
13
axios.all([axios({
url: "http://123.207.32.32:8000/home/multidata",
type: "get"
}), axios({
url: "http://123.207.32.32:8000/home/data",
type: "get",
params: {
type: 'pop',
page: 1
}
})]).then(axios.spread((data1, data2) => {
console.log(data1, data2)
}))

20200711203625.png

axios的全局配置

事实上, 在开发中可能很多参数都是固定的、这个时候我们可以进行一些抽取, 也可以利用axios的全局配置

axios.defaults.baseURL = '123.207.32.32:8000'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//导入 axios
import axios from "axios"

//全局配置
axios.defaults.baseURL = "http://123.207.32.32:8000"
axios.defaults.timeout = 5000 //单位: 毫秒

axios.all([axios({
url: "/home/multidata",
type: "get"
}), axios({
url: "/home/data",
type: "get",
params: {
type: 'pop',
page: 1
}
})]).then(axios.spread((data1, data2) => {
console.log(data1, data2)
}))

通过配置全局的baseURL可以省略掉这前面固定的部分,发送请求只需要填写后面的部分即可组合起来请求地址,发送请求。

请求配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{
// url 是用于请求的服务器 URL
url: '/user',

// method 是创建请求时使用的方法
method: 'get', // default

// baseURL 将自动加在 url 前面,除非 url 是一个绝对 URL。
// 它可以通过设置一个 baseURL 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',

// transformRequest 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data, headers) {
// 对 data 进行任意转换处理
return data;
}],

// transformResponse 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对 data 进行任意转换处理
return data;
}],

// headers 是即将被发送的自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},

// params 是即将与请求一起发送的 URL 参数
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
ID: 12345
},

// paramsSerializer 是一个负责 params 序列化的函数
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},

// data 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 transformRequest 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
},

// timeout 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeout: 1000,

// withCredentials 表示跨域请求时是否需要使用凭证
withCredentials: false, // default

// adapter 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},

// auth 表示应该使用 HTTP 基础验证,并提供凭据
// 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
auth: {
username: 'janedoe',
password: 's00pers3cret'
},

// responseType 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default

// responseEncoding indicates encoding to use for decoding responses
// Note: Ignored for `responseType` of 'stream' or client-side requests
responseEncoding: 'utf8', // default

// xsrfCookieName 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: 'XSRF-TOKEN', // default

// xsrfHeaderName is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default

// onUploadProgress 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},

// onDownloadProgress 允许为下载处理进度事件
onDownloadProgress: function (progressEvent) {
// 对原生进度事件的处理
},

// maxContentLength 定义允许的响应内容的最大尺寸
maxContentLength: 2000,

// validateStatus 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},

// maxRedirects 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // default

// socketPath defines a UNIX Socket to be used in node.js.
// e.g. '/var/run/docker.sock' to send requests to the docker daemon.
// Only either `socketPath` or `proxy` can be specified.
// If both are specified, `socketPath` is used.
socketPath: null, // default

// httpAgent 和 httpsAgent 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
// keepAlive 默认没有启用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),

// 'proxy' 定义代理服务器的主机名称和端口
// auth 表示 HTTP 基础验证应当用于连接代理,并提供凭据
// 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
proxy: {
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},

// cancelToken 指定用于取消请求的 cancel token
// (查看后面的 Cancellation 这节了解更多)
cancelToken: new CancelToken(function (cancel) {
})
}

axios的实例

为什么要创建axios的实例呢? 可以设置默认配置、规定配置

可以使用自定义配置新建一个 axios 实例 axios.create([config])

1
2
3
4
5
6
7
8
9
10
11
const instance = axios.create({
baseURL: "http://123.207.32.32:8000",
timeout: 5000
})

instance({
url: "/home/multidata",
type: "get"
}).then((res)=>{
console.log(res)
})

20200711221107.png

axios的封装

为了保证代码的后期维护、我们需要对axios进行封装

在src下创建network/request.js

1
2
3
4
5
6
7
8
9
import axios from 'axios'

export function request(config) {
const instance = axios.create({
baseURL: "http://123.207.32.32:8000",
timeout: 5000
})
return instance(config)
}

使用:

1
2
3
4
5
6
7
8
import {request} from "./network/request";

request({
url: "/home/multidata",
type: "get"
}).then((res) => {
console.log(res)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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: 50000
})

//发送网络请求
instance(config)
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}

使用:

1
2
3
4
5
6
7
8
9
import {request} from "./network/request";

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

axios的拦截器

在请求或响应被 thencatch 处理前拦截它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
查看代码

request.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import axios from 'axios'

export function request(config) {
const instance = axios.create({
baseURL: "http://123.207.32.32:8000",
timeout: 5000
})


instance.interceptors.request.use(config=>{
console.log("拦截的请求");
console.log(config)
// 拦截了请求要返回
return config;
},err=>{
console.log(err)
})


instance.interceptors.response.use(response=>{
console.log("拦截的响应");
console.log(response);
return response.data
},err=>{
console.log(err)
})

return instance(config)
}

main.js

1
2
3
4
5
6
7
8
9
import {request} from "./network/request";

request({
url: "/home/multidata",
type: "get"
}).then((res) => {
console.log('请求成功返回的结果');
console.log(res)
})

20200712100002.png