- axios的作用
- axios配置文件
- axios在使用中的一些坑
作用
axios其实就是vue-resourece的一个更优的基于Promise的解决方案,加上vue-resourece早已停止更新,fetch在配置中又十分的繁琐,这无疑让axios成为我的首选。
配置文件的说明
官方文档其实已经说明的很清楚了,在这里记录一下,便于断网的时候查询。
{
// `url` 是用于请求的服务器 URL
url: '/user',
// `method` 是创建请求时使用的方法
method: 'get', // 默认是 get
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data) {
// 对 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, // 默认的
// `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', // 默认的
// `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` 是承载 xsrf token 的值的 HTTP 头的名称
xsrfHeaderName: 'X-XSRF-TOKEN', // 默认的
// `onUploadProgress` 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// 对原生进度事件的处理
},
// `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; // 默认的
},
// `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // 默认的
// `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) {
})
}
// 响应结构
// 某个请求的响应包含以下信息
{
// `data` 由服务器提供的响应
data: {},
// `status` 来自服务器响应的 HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK',
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {}
}
其实这里的话是要
axios(config)
这样里面去的想一想这么多的配置文件要一股脑都塞进去,确实看起来是非常的不雅而且整个主代码会变得乱七八糟,没错,刚开始学习的我真的这样做了,后期几乎是完全没法维护的,后来我通过学习花裤衩大大的代码,才知道,这些东西是可以封装起来的,大概分出来两个文件。
首先是axios的配置文件(需要自己创建哦我个人是命名为request.js并且丢在src的utils文件夹中自己建的)
import axios from 'axios'
// axios配置信息
axios.defaults.withCredentials = true
const service = axios.create({
baseURL: process.env.BASE_API, // api 的 前缀url
timeout: 5000, // 请求超时
})
// 数据发送前的拦截器
service.interceptors.request.use(
config => {
return config
},
error => {
Promise.reject(error)
}
)
// 数据接受时的拦截器
service.interceptors.response.use((response) => {
return response
}, (err) => {
switch (err.response.status) {
case 500:
break;
case 429:
break;
default:
}
})
export default service
- 首先是这个配置文件,在
axios.create
这个方法中,有baseURL和timeout
这两个配置,前者指向的是webpack
的开发环境和生产环境,这个如果有自己配置的话,就在里面加一个baseURL
即可,如果还不清楚的话,建议通过console
来查看具体位置;再下面就是有两个拦截器,一个是数据发送前,一个是数据接受时,这两个拦截器用处很大,我这么配置之后,基本一目了然,在下面的res拦截器中,可以捕获到http错误码,可以通过判断和后端的错误码来给予用户最人性化的提示。- 而在数据发送前的这个拦截器则可以统一配置
header
等这一系列的东西从而避免在主代码中去重新设置这些东西,比如使用qs去转换需要发送的数据对吧,很方便的。
请求地址配置文件(同样是需要自己创建我个人是新建了一个目录api,然后把它放入新加的js文件中)
// 在此处导入之前配置的service
import request from 'request'
export default {
// 内容为请求的函数,例如:
post(data) {
return request({
url: "",
method: "post",
data
})
},
get(params) {
return request({
url: "",
method: "get",
params
})
},
}
这里的请求配置文件就很明了了,导入之后使用
export default
将其中的函数全部暴露出去方便调用,而函数内则是这样的一个结构,在函数内部配置一个url,method,data
,为什么要将这些配置分离出来配置而不是在之前的配置文件中使用,因为服务端提供的接口方式多是多样,可以是get,post,put,dele
其中的任意一个,而url则是前面相同部分的服务器地址后面的接口地址那部分,听起来是不是有点绕?举个栗子:现在有两个接口,https://skyserver.com/get_list 和 https://skyserver.com/get_list 那么我就可以设baseURL为 https://skyserver.com,而这里的url则是/get_list
或者是/get_list
,明白了吗?每一个接口我们只需要更改后面的接口名和请求方式就好了。
如何去使用?
emm,其实使用方法有很多,我个人推荐是去
main.js
文件中去引入,例如我引入之后的名字是api那么我就可以使用这行代码Vue.prototype.$api = api
意思为将这个挂载到vue的原型中去,这样的好处就是我们可以直接使用this.$api.get()
的方式进行调用,由于axios本身就是一个基于Promise
的项目,其实就可以直接使用async and await
的形式来进行调用,借助webpack
的一部分功能让自己的代码本体变得不再那么冗余。
踩过的坑
- axios本身不会发送cookie,需要你自己加上
axios.defaults.withCredentials = true
这句代码才会发送cookie,但是会存在跨域问题,在这里由于我只使用了nodejs作为后端所以只举例nodejs如何解决这个跨域问题的:
首先我使用的是的是express框架,不过影响不大,毕竟koa和其他的都是差不多的原理。话不多说先上代码:
// 我们可以直接获取访问服务器的来源直接赋值过去,虽然方便,但是要知道本身这个是防御XSS攻击,这么设置之后的风险阅读者应该要须知。
let origin = req.header.origin
//访问控制允许来源,有人会问为什么这里不是一个'*'呢,因为在启用了cookie之后,是不允许使用通配符的,所以在当需要发送cookie的场景中
res.header('Access-Control-Allow-Origin', origin);
//访问控制允许报头 X-Requested-With: xhr请求
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,X-Token");
//访问控制允许方法
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
// 它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
res.header("Access-Control-Allow-Credentials",true);
//自定义头信息,表示服务端用nodejs,其实你也可以发送其他的2333虽然意义不明
res.header('X-Powered-By', 'nodejs');
// 定义发送的数据格式
res.header('Content-Type', 'application/json;charset=utf-8');
这里出现的弊端,想必一眼就看出来了对吗?这里允许了所有来访者的url,但是事实上我们并不能这样允许,因为这样是有安全问题的!so,做个判断不就好啦:
// 这里规定一个白名单,允许哪些域名访问,是一个数组
let whitList = ['','']
// 这里则使用的是es6的语法,检查该变量是否存在于数组中
// 和es5中的 `indexOf()` 有异曲同工之妙,但是它返回的是一个布尔值,除了不能够定位元素的位置,但是用在此处很棒不是么~
if(whitList.includes(origin)){
// 这里是上面的那段代码
}
- axios是基于es6语法的,你可能会遇到
Promise is not function
的问题,通常出现在老旧浏览器上,可以通过bable来进行转换。下图是其浏览器的支持。
|
|
|
|
|
|
---|---|---|---|---|---|
Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ |
- 它拦截接收报错的信息是在
err.response
中,而不是直接的err就可以获取到,这一点是很坑的,一直以来我都以为是在err中,导致始终无法捕捉到http状态值以及报错信息,其实官方文档也有说明,如果我不是那么的星际也不会犯这种低级错误