本章概要
- 创建实例
- 配置默认值
- 拦截器
15.6 创建实例
可以使用自定义配置调用 axios.create([config]) 方法创建一个 axios 实例,之后使用该实例向服务端发起请求,就不用每次请求时重复设置配置选项了。如下:
const instance = axios.create({
baseURL:'https://some-domain.com/api/',
timeout:1000,
headers:{'X-Custom-Header':'foobar'}
})
15.7 配置默认值
对于每次请求相同的配置选项,可以通过为配置选项设置默认值来简化代码的编写。项目中使用的全局 axios 默认值可以在项目的入口文件 main.js 中按照以下形式进行设置。
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.withCredentials = true;
也可以在自定义实例中设置配置默认值,这些配置选项只有在使用该实例发起请求时才生效。如下:
// 创建实例时设置配置默认值
const instance = axios.create({
baseURL:'https://api.example.com'
})
// 实例创建后更改默认值
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN
配置将按优先级顺序进行合并。顺序是先在 lib/defaults.js 中找到的库的默认值,然后是实例的 defaults 属性,最后是请求的 config 参数。后者将优先于前者。如下:
// 使用由库提供的配置默认值来创建实例
// 此时超时配置的默认值是 0
var instance = axios.create();
// 覆写库的超时默认值
// 现在,在超时前,使用该实例发起的所有请求都会等待 2.5 s
instance.defaults.timeout = 2500;
// 在发起请求时,覆写超时值
instance.get('/login',{
timeout:5000
})
15.8 拦截器
有时需要统一处理 HTTP 的请求和响应,如登录验证,这时就可以使用 axios 的拦截器,分为请求拦截器和响应拦截器,他们会在请求或响应被 then() 或 catch() 方法处理前拦截他们。axios 的拦截器的使用形式如下:
// 添加请求拦截器
axios.interceptors.request.use(function (config){
// 在发送请求之前做些什么
return config;
},function(err){
// 对请求错误做些什么
return Promise.reject(err);
});
// 添加响应拦截器
axios.interceptors.response.use(function (res){
// 对响应数据做些什么
return res;
},function(err){
// 对响应错误做些什么
return Promise.reject(err);
})
《14.10.1 小节》 使用全局守卫实现了一个用户登录验证的例子,不过这种方式只是简单的前端路由控制,用户一旦成功登陆,前端就保存了用户登录的状态,允许用户访问受保护的资源。
如果在这期间,该用户在服务端失效了。例如,用户长时间未操作、服务端强制下线,或者管理员将该用户拉入黑名单,那么前端就应该及时更新用户状态,对用户的后续访问做出控制。
在这种情况下,就应该使用 axios 的拦截器结合 HTTP 状态码进行用户是否已登录的判断。如下:
// 请求拦截器
axios.interceptors.request.use(
config => {
if (token) {
// 判断是否存在 token,如果存在,则每个 HTTP header 都加上 token
}
return config;
},
err => {
return Promise.reject(err);
}
)
// 响应拦截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if(error.response){
switch(error.response.status){
case 401:
// 如果返回 401 ,则清除 token 信息并跳转到登录页面
router.replace({
path:'login',
query:{redirect:router.currentRoute.fullPath}
})
}
}
return Promise.reject(error.response.data);
}
)
如果之后想移除拦截器,则可以按以下方式调用。
const myInterceptors = axios.interceptors.request.use(function(){
// ...
})
axios.interceptors.request.reject(myInterceptors)
也可以为自定义的 axios 实例添加拦截器。如下:
const instance = axios.create();
instance.interceptors.request.use(function(){
// ...
})