Javascript Vue.js:Nuxt错误处理

Javascript Vue.js:Nuxt错误处理,javascript,vue.js,vuejs2,vuex,nuxt.js,Javascript,Vue.js,Vuejs2,Vuex,Nuxt.js,在使用vuex设置错误处理方面有些困难。似乎有很多方法可以做到这一点,关于正确的错误处理的文档很少。我已经尝试了四种选择,尽管我还没有找到令人满意的解决方案 备选方案1-捕获和处理组件上的错误 在页面/login.vue: export const actions = { login({ commit }, { email, password }) { return this.$axios.post('/api/login', { email,

在使用vuex设置错误处理方面有些困难。似乎有很多方法可以做到这一点,关于正确的错误处理的文档很少。我已经尝试了四种选择,尽管我还没有找到令人满意的解决方案


备选方案1-捕获和处理组件上的错误

页面/login.vue:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
存储/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
专业人士

缺点

  • vuex中未处理和存储错误
  • 在组件方法中引入了大量样板代码

备选方案2-vuex中的捕获和处理错误

页面/login.vue:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
存储/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
专业人士

  • vuex可以从任何组件访问错误对象
  • 可以在布局中使用反应性错误组件,该组件在错误状态更改时显示
缺点

  • 我不确定是否有办法跟踪错误的来源,它是从哪个组件抛出的

备选方案3-使用axios拦截器捕获错误

在plugins/axios.js中:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
页面/login.vue:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
存储/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
专业人士

  • 全局错误处理
  • 无需捕获vuex或组件中的错误
  • 无锅炉铭牌代码
缺点

  • 所有异常都未经处理,这意味着非axios错误未经处理

备选方案4-自定义错误插件

我一直在尝试实现一个能够捕获所有异常的自定义插件,但我并没有成功地让它工作

在plugins/catch.js中:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
页面/login.vue:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}
专业人士

  • 没有样板
  • 插件中捕获的所有错误
缺点

  • 我做不到(

我的印象是,在vue/nuxt中缺少关于错误处理的文档。有人可以使用第四种方法吗?这是否理想?有其他方法吗?什么是常规方法


感谢您抽出时间!

行动中使用
承诺

vuex中的示例:

NEW_AUTH({ commit }) {
    return new Promise((resolve, reject) => {
      this.$axios.$get('/token').then((res) => {
        ...
        resolve();
      }).catch((error) => {
        reject(error);
      })
    })
  }
第页:

this.$store.dispatch('NEW_AUTH')
   .then(() => ... )
   .catch((error) => ... )

要解决备选方案2的问题,您可以

(a) 传递组件的名称,甚至传递对组件的引用,或

(b) 您可以将错误保留在发出调用的组件的状态中。然后,您可以在组件中检查是否存在错误并显示它。为此,您可以使用mixin放弃对锅炉板的需要

店内/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
            commit('save_to_state', { response: res });
        }).catch((error) => {
            commit('save_to_state', { error });
        });
    },
}

在每个Vuex模块的状态下创建一个
错误
键。然后将给定组件的错误分派到其相对Vuex模块。然后创建一个全局处理程序以监视单独Vuex模块中的错误,如果触发了错误,则显示错误

// store/auth.js

export const state = () => {
  return {
    success: null,
    error: null
  }
}

export const actions = {
  async login({ commit }, { email, password }) {
    try {
      const response = await axios.post('/api/login', {
        email,
        password
      })
      commit('SET_SUCCESS', response)
    } catch(err) {
      commit('SET_ERROR', error)
    }
  }
}

export const mutations = {
  SET_SUCCESS(state, payload) {
    state.success = payload
  },
  SET_ERROR(state, payload) {
    state.error = payload
  }
}
选项#4不起作用的原因是您返回了一个从未执行过的函数:

函数catchPlugin(outerFunction){
返回函数异步内部函数(args){
试一试{
常量数据=等待外部函数(args);
返回{data}
}捕获(错误){
返回{error}
}
}
}
用法:

const execute=catchPlugin((args)=>{
//做点什么
})
执行('myArgument');
如您所见,您还需要执行内部函数,以使示例正常工作:

onLogin:this.$catch(异步函数(){
等待此消息。$store.dispatch('auth/login',{email:this.email,password:this.password});
这个。$router.push('/home');
})(),//注意():-)
但是。。。我相信处理组件中的错误不是一件坏事,因为它与视图组件紧密耦合。例如,考虑一个登录组件,我们现在看到的是一个全局错误处理程序(toastr),如果用户名/密码不正确,它将显示一条toast消息。根据我的经验,这不是最好的行为,这是一个很好的起点,但最好是在组件附近添加错误消息,以显示到底出了什么问题。这意味着您必须始终在组件本身中添加错误处理(与UI相关)

我们公司的同事也在努力解决这一问题,他们正在开发同一产品。一个是添加错误处理,另一个不是。。在我看来,唯一的解决办法是教育开发人员始终添加正确的错误处理。
async/await
的语法没有那么糟糕:

methods: {
   async login (email, password) {
      try {
         await this.$store.dispatch('auth/login', { email, password })
         // do something after login
      } catch (error) {
         // handle error
      }
   }
}

关于您的
con
,最后一件事是:未在vuex中处理和存储错误。。为什么这是个骗局?您是否需要使错误全局可用?我经常看到的是,人们在
vuex
中放置了太多无用的状态,而这些状态只用于组件本身。拥有本地组件状态并不坏。因为它是关于登录的,所以应该只在登录组件中知道这个错误。

我认为关于axios拦截器的方法3适合全局处理错误。最好的方法是使用
中间件
这是不对的-Nuxt中的所有操作都是异步的,因此无需在promise中再次包装它,只需返回对
$get
的调用,因为它已经返回了一个承诺
// app.vue

export default {
  created() {
    this.$store.subscribe((mutation, state) => {
      if (mutation.type.includes('ERROR')) {
        // display error in global error output
        console.log(mutation.payload)
      }
    })
  }
}
methods: {
   async login (email, password) {
      try {
         await this.$store.dispatch('auth/login', { email, password })
         // do something after login
      } catch (error) {
         // handle error
      }
   }
}