使用 vuex 处理 vue/axios 中的全局 http 响应错误 [英] Global http response error handling in vue/axios with vuex

查看:44
本文介绍了使用 vuex 处理 vue/axios 中的全局 http 响应错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试修复我的 VueJS SPA 中出现不确定状态的行为.应用程序不知道 JWT 已经过期,因此将自己显示为用户仍在登录.例如,这可能在休眠后发生.

I'm trying to fix a behavior in my VueJS SPA wherein a limbo state arises. The app doesn't know the JWT has already expired and therefore presents itself as if the user is still logged in. This can happen after hibernation, for example.

这些用户可以继续向 API 发出任何请求,但最终会得到 401 响应(而且是正确的).

These users can keep on making any request to the API, but end up with a 401 response (and correctly so).

我想要一个用于 401 响应的全局处理程序.(这将是:从 vuex 中清除与用户相关的所有内容,并像用户一样呈现页面,并弹出登录表单等.")否则,我将不得不为每个请求编写一个 401 处理程序.

I'd like to have a global handler for 401 responses. (This would be: "clear everything user-related from vuex and present the page as if the user was a guest, with login form popup, etc.") Otherwise, I would have to write a 401 handler for EVERY request.

我可以向 axios 添加响应拦截器,它们工作正常.但是,这些拦截器无法访问 Vuex(或 Vue).

I can add response interceptors to axios, and they work fine. These interceptors don't have access to Vuex (or Vue), though.

每当我尝试将 Vuex 或 Vue 导入我的 Axios 时,我都会得到循环依赖(当然)并且一切都中断了.

Whenever I try to import Vuex or Vue into my Axios, I get circular dependencies (of course) and everything breaks.

如果我只是抛出/返回错误,我仍然需要在每个请求上单独处理它.如何从 axios 拦截器中分派 this.$store 上的方法?

If I just throw/return the error, I still have to handle it separately on every request. How can I dispatch methods on this.$store from within an axios interceptor?

Axios 文件包含一个 export default class API,它在 main.js 中全局添加到 Vue 中:

The Axios file contains an export default class API that is added to Vue globally in main.js:

import api from 'Api/api'
// ...
Vue.prototype.$http = api

认为必须有一种方法可以从 $http 访问 Vue,因为它是一个全局实例方法.但我好像弄错了?

I had thought there has to be a way to access Vue from $http, since it's a global instance method. But I appear to be mistaken?

main.js

// ...
import api from 'Api/api'
// ...
Vue.prototype.$http = api

new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: { App },
  vuetify: new Vuetify(opts),
});

api.js

import Client from './ApiClient'

const apiClient = new Client({ basePath: process.env.VUE_APP_API_URL })

const api = {
  get(url) {
    return apiClient._get(`${basePath}/${url}`)
  },
  post(url, data) {
    return apiClient._post(`${basePath}/${url}`, data)
  },
  // ...
}
export default api

ApiClient.js

const axios = require('axios')

const errorHandler = (error) => {
  if (error.response.status === 401) {
    store.dispatch('user/logout') // here is the problem
  }
  return Promise.reject({ ...error })
}


export default class API {
  constructor(options) {
    this.options = Object.assign({ basePath: '' }, options)
    this.axios = axios.create({ timeout: 60000 })
    this.axios.interceptors.response.use(
      response => response,
      error => errorHandler(error)
    )
  }
  // ...
}

ApiClient.js 中导入 store 会导致依赖循环:我假设是因为我在其中导入了 Vue?

Importing store in ApiClient.js results in a dependency cycle: I assume because I'm importing Vue in it?

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import PersistedState from 'vuex-persistedstate'
import CreateMutationsSharer from 'vuex-shared-mutations';
import SecureLS from 'secure-ls';
// import modules

Vue.use(Vuex);
const ls = new SecureLS({ encodingType: 'aes' });

export default new Vuex.Store({
  // options
})

推荐答案

conf
import Axios from 'axios'
import IdentityProxy from './IdentityProxy.js'
import UsuariosProxi from './UsuariosProxi'
import ZonasProxi from './ZonasProxi'

//axios
Axios.defaults.headers.common.Accept='application/json'
//Axios.defaults.headers.common['Access-Control-Allow-Origin'] = '*';

Axios.interceptors.request.use(
    config => {
        let token = localStorage.getItem('access_token');

        if(token){
            config.headers= {
                'x-access-token': `${token}`
            }
        }
        return config;
    },
    error => Promise.reject(error)
);
Axios.interceptors.response.use(
    response => response,
    error => {
      if (error.response.status===403||error.response.status===401) {
        localStorage.removeItem('access_token');
        window.location.reload(true);
      }
   
      return Promise.reject(error);
    }
  );
let url=null

if(localStorage.getItem("config")!==null){
    let config = JSON.parse(localStorage.getItem("config"))
    url = config
}

console.log(url)
export default{
    identityProxy: new IdentityProxy(Axios, url),
    _usuarioProxi: new UsuariosProxi(Axios, url),
    _zonasProxi: new ZonasProxi(Axios, url),
}
//
export default class IdentityProxy{

    constructor(axios,url){
    this.axios = axios;
    this.url =url;
    }

    register(params){
        return this.axios.post(this.url+'/identity/register',params)
    }

    login(params){
        
        return this.axios.post(this.url+'/auth/signin',params)
    }
}
//
export default class UsuariosProxi{
    constructor(axios,url){
    this.axios = axios;
    this.url =url;
    }

    /* getAll(){
        return this.axios.get(this.url+'/users')
    } */
    getAll(page, take) {
        return this.axios.get(this.url + `/users?page=${page}&take=${take}`);
    }
    create(params) {
        return this.axios.post(this.url + '/auth/signup', params);
    }

    get(id) {
        return this.axios.get(this.url + `/users/${id}`);
    }
    update(id, params) {
        return this.axios.put(this.url + `/users/${id}`, params);
    }

    remove(id) {
        return this.axios.delete(this.url + `/users/${id}`);
    }
    //-----APARTE SOLO TRAE LISTA DE ROLES--------
    getRoles() {
        return this.axios.get(this.url + '/users/newrol');
    }
}
//st
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const state = {
    user:null
}
export default new Vuex.Store({
    state
});

这篇关于使用 vuex 处理 vue/axios 中的全局 http 响应错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆