Vue.js: Nuxt error handling

廉价感情. 提交于 2020-01-01 03:55:05

问题


Struggling a bit to set up error handling with vuex. There seems to be quite a few ways to do so and little documentation on proper error handling. I've been experimenting with four alternatives, though I haven't found a satisfying solution yet.


Alternative 1 - Catching and processing errors on component

in pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            }).catch((error) {
                // handle error in component
            });
        },
    },
}

in store/auth.js:

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

PROS

  • Hmm.

CONS

  • Errors not handled and stored in vuex.
  • Introduces lots of boilerplate code in component methods.

Alternative 2 - Catching and processing errors in vuex

in pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            });
        },
    },
}

in store/auth.js:

export const actions = {
    login({ commit }, { email, password }) {
        return this.$axios.post('/api/login', {
            email,
            password,
        }).then((res) => {
            doSomething(res);
        }).catch((error) => {
            // store error in application state
            commit('SET_ERROR', error);
        });
    },
}

PROS

  • Error object is accessible with vuex from any component
  • Could use a reactive error component in layout, which is revealed when the error state changes.

CONS

  • I'm not sure if there is a way to track the source of the error, from which component it was thrown.

Alternative 3 - Catching errors using axios interceptors

in plugins/axios.js:

export default function({ $axios, store }) {
    $axios.onError(error => {
        store.dispatch('setError', error);
    });
}

in pages/login.vue:

export default {
    methods: {
        onLogin() {
            this.$store.dispatch('auth/login', {
                email: this.email,
                password: this.password,
            }).then(() => {
                this.$router.push('/home');
            });
        },
    },
}

in store/auth.js:

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

PROS

  • Global error handling
  • No need to catch errors in either vuex or component
  • No boiler-plate code

CONS

  • All exceptions are unhandled, meaning non-axios errors are uncaught.

Alternative 4 - Custom error plugin

I've been experimenting in implementing a custom plugin that catches all exceptions, but I'm not succeeding in making it work.

in plugins/catch.js:

export default (ctx, inject) => {
    const catchPlugin = function (func) {
        return async function (args) {
            try {
                await func(args)
            } catch (e) {
                return console.error(e)
            }
        }
    };
    ctx.$catch = catchPlugin;
    inject('catch', catchPlugin);
}

in pages/login.vue:

export default {
    methods: {
        onLogin: this.$catch(async function () {
            await this.$store.dispatch('auth/login', { email: this.email, password: this.password });
            this.$router.push('/home');
        }),
    },
}

PROS

  • No boilerplate.
  • All errors caught in plugin.

CONS

  • I cannot make it work. :(

My impression is that there is a lack of documentation on error handling in vue/nuxt. Could anyone get the fourth alternative to work? Would this be ideal? Any other alternatives? What is conventional?

Thank you for your time!


回答1:


Use Promise in action

Example in vuex:

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

In page:

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



回答2:


To address the Con from Alternative 2 you can either

(a) pass in the name of the component or even a reference to the component or

(b) you can persist the error in the state for the component that made the call. Then in your component you could check if there is an error and display it. For that you could use a mixin to forgo the need for boiler plate.,

in store/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 });
        });
    },
}



回答3:


Create an error key in the state of each Vuex module. Then dispatch the error for a given component to its relative Vuex module. Then create a global handler to watch for errors in the separate Vuex modules and, if one is triggered, display the error.

// 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
  }
}
// auth.vue

export default {
  methods: {
    onLogin() {
      try {
        await this.$store.dispatch('auth/login', {
          email: this.email,
          password: this.password
        })
        if (this.$store.state.auth.success) this.$router.push('/home')
      } catch (err) {
        console.log(err)
      }
    }
  }
}
// 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)
      }
    })
  }
}


来源:https://stackoverflow.com/questions/51247371/vue-js-nuxt-error-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!