【问题标题】:Making axios global in Vue project is not working在 Vue 项目中使 axios 全局化不起作用
【发布时间】: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 一次并在任何地方使用它,而不是在每个文件中导入和使用不同的实例。

我参考了thisthis,并尝试了以下方法。

// 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;。错误处理程序也没有返回被拒绝的承诺,这可能证明是有问题的。

标签: javascript typescript vue.js axios


【解决方案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) 
          });
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-13
        • 2022-01-11
        • 2019-07-27
        • 1970-01-01
        • 2021-08-27
        • 2017-09-10
        相关资源
        最近更新 更多