axios的基础配置及跨域

1,387 阅读3分钟

在开发的过程中,经常需要对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里也有相关信息。

image.png

但是在instance.interceptors.response方法中执行的是error对象,它的输出里完全没有response信息。

image.png 同时,在看response时发现只展示了Failed to load response data: No data found for resource with given identifier,这里的描述就是跨域的问题。

image.png

通过控制台console也能看到跨域的错误。 image.png

在开发过程中发现接口正常的时候预检请求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