在开发的过程中,经常需要对axios做简单处理,通过axios.create
创建新实例,做统一处理。
const instance = axios.create({
baseURL: '/api', // baseURL: 'http:www.baidu.com'
timeout: 180000,
// headers: { 'x-requested-with': 'XMLHttpRequest' },
withCredentials: true
})
instance.defaults.headers.common['XX'] = XX
instance.interceptors.request.use((config) => {
/** */
return config
})
instance.interceptors.response.use((res) => {
const json = res.data
// 统一处理,譬如错误提示等
if (json.data && (json.data.code < 0 || json.data.error)) {
res.data.code = -1
res.data.message = json.data.msg || json.data.message
if (res.data.message) {
console.error(res.data.message)
}
}
return res.data
}, (error) => {
// 错误处理
})
首先,介绍下常用的axios config: baseURL、timeout、withCredentials,还有一些不常用的config配置看axios文档
config | 描述 | 其它 |
---|---|---|
baseURL | 将自动加在 url 前加载除非 url 是一个绝对 URL。 | 设置绝对路径‘www.a.com’, 则请求按照baseULR + api ,这种情况需要考虑跨域问题。如果设置相对路径‘/’,请求是当前域名+api |
timeout | 指定请求超时的毫秒数(0 表示无超时时间),如果请求花费了超过 timeout 的时间,请求将被中断 | 后端很多服务器的请求设置5000,响应1800000,仅供参考,参数自己根据情况设置 |
withCredentials | 表示跨域请求时是否需要使用凭证 | 譬如:设置为true, 请求头里会含有cookie信息;否则,没有 |
headers | 是即将被发送的自定义请求头 | {'X-Requested-With': 'XMLHttpRequest'}表示是传统 |
其次,经常碰到需要在headers中加一些参数,譬如鉴权authorization
instance.defaults.headers.common['authorization'] = token
const instance = axios.create({
baseURL: '/api', // baseURL: 'http:www.baidu.com'
timeout: 180000,
headers: { 'x-requested-with': 'XMLHttpRequest' },
withCredentials: true
})
再次,会经常用到拦截器对数据或相关逻辑做统一处理
instance.interceptors.request.use((config) => {
/** 在发出请求是对某些做统一处理,譬如根据api不一样,采用不同的baseURL*/
if (config.url.include('/test')) {
config.baseURL = 'http://www.a.com'
} else {
config.baseURL = 'http://www.b.com'
}
return config
})
instance.interceptors.response.use((res) => {
const json = res.data
// 统一处理,譬如错误提示等
if (json.data && (json.data.code < 0 || json.data.error)) {
res.data.code = -1
res.data.message = json.data.msg || json.data.message
if (res.data.message) {
// 错误提示
console.error(res.data.message)
}
}
return res.data
}, (error) => {
// 错误处理
})
最后,介绍下取消token的情况,主要是在请求中添加cancelToken,一个token用一个source记录,如果有多个需要建立多个cancelToken.source
import { CancelToken } from 'axios';
const source = CancelToken.source();
axios.get('/first', {
cancelToken: source.token
})
const someMethod = async () => {
if (source) {
source.cancel('这里是字符串,可以写取消原因')
}
await axios.get('/second');
}
项目问题
在一次项目开发中,碰到了如下的问题,instance.interceptors.response
拦截器中获取不到response的值,在请求的headers里可以看到返回的状态码400, 以及response Headers里也有相关信息。
但是在instance.interceptors.response
方法中执行的是error对象,它的输出里完全没有response信息。
同时,在看response时发现只展示了
Failed to load response data: No data found for resource with given identifier
,这里的描述就是跨域的问题。
通过控制台console也能看到跨域的错误。
在开发过程中发现接口正常的时候预检请求options和当前请求‘/profile’都是200,但是当我token过期(只是我测试的情况),接口返回400 bad request就会出现跨域的问题。通过charles代理/postman模拟,都拿到response body。同时,我报错的情况下,它的options预检请求状态是200,理论是配置了跨域的,但是后面get请求的‘/profile’就400,对比发现它缺少跨域的相关信息,譬如Access-Control-Allow-Origin
,通过charles代理在response中添加Access-Control-Allow-Origin
,数据就能正常获取了。因此,碰到上面浏览器response获取不到,以及提示Failed to load response data: No data found for resource with given identifier
,查看response header, 大概率就是跨域的问题
参考文档:
1. axios
2. XMLHttpRequest