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!