Vue.js: Nuxt error handling

nomadoda picture nomadoda · Jul 9, 2018 · Viewed 14.7k times · Source

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!

Answer

Adriano Resende picture Adriano Resende · Aug 16, 2018

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) => ... )