在 Vue 项目中使 axios 全局化不起作用
Posted
技术标签:
【中文标题】在 Vue 项目中使 axios 全局化不起作用【英文标题】:Making axios global in Vue project is not working 【发布时间】:2019-12-15 23:41:36 【问题描述】:直到现在,我一直在我想发出 HTTP 请求的每个 Vue 组件中导入 axios,就像这样。
<script lang="ts">
import axios from 'axios';
@Component
export default class ExamplePage extends Vue
created(): void
axios.post(some_path);
但是,现在我想为所有 axios 请求定义一个全局拦截器,基本上是为了捕获来自后端服务器(Rails)的所有 401 unauthorized
响应并注销用户。
到目前为止我的理解是你必须实例化 axios 一次并在任何地方使用它,而不是在每个文件中导入和使用不同的实例。
我参考了this 和this,并尝试了以下方法。
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
document.addEventListener('DOMContentLoaded', () =>
new Vue(
el: '#application',
router,
render: (h) => h(App),
);
);
axios.interceptors.response.use(
response => response,
error =>
const status = error.response;
if(status === 401)
// do stuff
);
Vue.prototype.$http = axios
当我尝试在另一个文件中调用 this.$http.put(...)
时,它说属性 $http
不存在(我猜这是因为该组件上下文中的 this
是组件本身,但我不确定)。我该如何解决这个问题?
[UPDATE]感谢回复,我决定在单独的文件中初始化 axios 实例,然后改用它。但是,这仍然不起作用。 401 响应似乎根本没有触发拦截器。
是否需要一些额外的配置?
// axios-instance.ts
import axios, AxiosInstance from 'axios';
const axiosInstance: AxiosInstance = axios.create();
axiosInstance.interceptors.response.use(
response => response.data,
async function(error)
console.log("THIS IS THE 401 INTERCEPTOR")
const status = error.response;
if(status === 401)
// Log out user
);
export default axiosInstance;
// Some component
<script lang="ts">
import axiosInstance from 'axios-instance';
@Component
export default class ExamplePage extends Vue
created(): void
axiosInstance.post(some_path);
【问题讨论】:
你为什么不试试github.com/imcvampire/vue-axios? 你不能在application.js
中写this.$http.interceptors
,你需要使用axios.interceptors
。如果这不是您的问题的原因,您能否更新您的问题,以包括对 put
的呼叫不起作用。没有一些上下文,很难判断你是否正确地做到了这一点。
@skirtle 我将我对 axios 实例的引用更改为 axios
,但是当我尝试在任何其他文件中调用它时,它仍然会出现“属性 '$http' 在类型'ExamplePage 上不存在' '(组件名称)”。正如我在上面所写的,这可能是因为该组件上下文中的this
指的是组件本身。进一步的建议表示赞赏。
自从我上次查看以来,问题似乎发生了重大变化,现在在 TypeScript 中。当问题变化如此之大时,很难给出任何答案。在您的最新代码中,您有const status = error.response;
,它可能应该是const status = error.response.status;
。错误处理程序也没有返回被拒绝的承诺,这可能证明是有问题的。
【参考方案1】:
不能直接解决您的问题,但我创建 axios 实例的方式是:
// axios-instance.js
import axios from 'axios'
const instance = axios.create(
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: 'X-Custom-Header': 'foobar'
);
export default instance
在你刚刚导入实例之后
// application.js
import axios from '../../axios-instance'
【讨论】:
【参考方案2】:当你不在 vue 实例中时,你不能使用 this。 试试这个:
// application.js
import '../assets/sass/base.sass';
import App from '../app';
import Vue from 'vue';
import VueRouter from 'vue-router';
import axios from 'axios';
import router from '../routes';
Vue.use(VueRouter);
axios.interceptors.response.use(
response => response,
error =>
const status = error.response;
if(status === 401)
// do stuff
);
Vue.prototype.$http = axios;
const VueInstance = new Vue(
el: '#application',
router,
render: (h) => h(App),
);
现在您可以使用 this.$http 发出 HTTP 请求:
<script>
export default
methods:
doStuff()
this.$http.post('path_to_post_request').then(( data ) =>
// do something with received data
).catch((e) => );
</script>
【讨论】:
当我尝试在任何组件文件中使用this.$http
时,它会显示“ 类型上不存在属性'$http'”。不知何故,Vue.prototype
似乎在这里不起作用。【参考方案3】:
我遇到了同样的问题。 在 Axios API 文档中并不清楚应该在响应拦截器的错误回调中拦截错误响应。
应该这样做:
axios.interceptors.response.use(function (response)
//This is the success callback in case u ever need it
return response;
, function (error)
// This is the callback I was talking about.
// Do something with request error
// Tip: error.response is the actual response with error code
return Promise.reject(error);
)
这可以在Axios API Documentation - Interceptors section看到
【讨论】:
【参考方案4】:我建议你在单独的js文件中实现axios实例:
// utils/request.js
import axios from 'axios'
const service = axios.create(
baseURL: '',
headers: ,
withCredentials: true,
// ...other options
)
// request interceptor
service.interceptors.request.use(config =>
// ...
return config
, err =>
return Promise.reject(err)
)
// response interceptor
service.interceptors.response.use(response =>
// ...
return response
, err =>
return Promise.reject(err)
)
export default service
然后你可以像这样使用http请求:
import request from '@/utils/request'
request(
url: '',
method: 'post',
data:
).then(res =>
// Do something after the request is successful
).catch(err =>
// Do something after the request fails
)
【讨论】:
嗨,你能看一下我上面的更新吗?我按照您的评论进行了尝试,但仍然遇到让所有 axios 实例都使用拦截器的问题。【参考方案5】:尝试实现一个服务:
src/services/yourservice.js
import axios from 'axios'
const apiClient = axios.create(
baseURL: 'https://example.com/api',
withCredentials: false,
timeout: 1000,
headers:
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic ' + btoa('api_username_here' + ':' + 'api_password_here')
)
export default
getOrders()
return apiClient.get('/orders?status=processing')
,
getProducts(id)
return apiClient.get('/products/' + id)
,
在组件中使用服务: src/component/yourcomponent.vue
import YourService from '@/services/YourService.js';
data()
return
orders: null, //Typescript
,
created()
yourservice.getOrder(id).then(response =>
this.orders = response.data
).catch(error =>
console.log(error)
);
【讨论】:
以上是关于在 Vue 项目中使 axios 全局化不起作用的主要内容,如果未能解决你的问题,请参考以下文章