title: Vue.js: Nuxt error handling
body: <p>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.</p>
  
  <hr>
  
  <p><strong>Alternative 1 -</strong> <em>Catching and processing errors on component</em></p>
  
  <p><em>in</em> <strong><em>pages/login.vue:</em></strong></p>
  
  <pre><code>export default {
      methods: {
          onLogin() {
              this.$store.dispatch('auth/login', {
                  email: this.email,
                  password: this.password,
              }).then(() =&gt; {
                  this.$router.push('/home');
              }).catch((error) {
                  // handle error in component
              });
          },
      },
  }
  </code></pre>
  
  <p><em>in</em> <strong><em>store/auth.js:</em></strong></p>
  
  <pre><code>export const actions = {
      login({ commit }, { email, password }) {
          return this.$axios.post('/api/login', {
              email,
              password,
          }).then((res) =&gt; {
              doSomething(res);
          });
      },
  }
  </code></pre>
  
  <p><strong>PROS</strong></p>
  
  <ul>
  <li>Hmm.</li>
  </ul>
  
  <p><strong>CONS</strong></p>
  
  <ul>
  <li>Errors not handled and stored in vuex.</li>
  <li>Introduces lots of boilerplate code in component methods.</li>
  </ul>
  
  <hr>
  
  <p><strong>Alternative 2 -</strong> <em>Catching and processing errors in vuex</em></p>
  
  <p><em>in</em> <strong><em>pages/login.vue:</em></strong></p>
  
  <pre><code>export default {
      methods: {
          onLogin() {
              this.$store.dispatch('auth/login', {
                  email: this.email,
                  password: this.password,
              }).then(() =&gt; {
                  this.$router.push('/home');
              });
          },
      },
  }
  </code></pre>
  
  <p><em>in</em> <strong><em>store/auth.js:</em></strong></p>
  
  <pre><code>export const actions = {
      login({ commit }, { email, password }) {
          return this.$axios.post('/api/login', {
              email,
              password,
          }).then((res) =&gt; {
              doSomething(res);
          }).catch((error) =&gt; {
              // store error in application state
              commit('SET_ERROR', error);
          });
      },
  }
  </code></pre>
  
  <p><strong>PROS</strong></p>
  
  <ul>
  <li>Error object is accessible with vuex from any component</li>
  <li>Could use a reactive error component in layout, which is revealed when the error state changes.</li>
  </ul>
  
  <p><strong>CONS</strong></p>
  
  <ul>
  <li>I'm not sure if there is a way to track the source of the error, from which component it was thrown.</li>
  </ul>
  
  <hr>
  
  <p><strong>Alternative 3 -</strong> <em>Catching errors using axios interceptors</em></p>
  
  <p><em>in</em> <strong><em>plugins/axios.js:</em></strong></p>
  
  <pre><code>export default function({ $axios, store }) {
      $axios.onError(error =&gt; {
          store.dispatch('setError', error);
      });
  }
  </code></pre>
  
  <p><em>in</em> <strong><em>pages/login.vue:</em></strong></p>
  
  <pre><code>export default {
      methods: {
          onLogin() {
              this.$store.dispatch('auth/login', {
                  email: this.email,
                  password: this.password,
              }).then(() =&gt; {
                  this.$router.push('/home');
              });
          },
      },
  }
  </code></pre>
  
  <p><em>in</em> <strong><em>store/auth.js:</em></strong></p>
  
  <pre><code>export const actions = {
      login({ commit }, { email, password }) {
          return this.$axios.post('/api/login', {
              email,
              password,
          }).then((res) =&gt; {
              doSomething(res);
          });
      },
  }
  </code></pre>
  
  <p><strong>PROS</strong></p>
  
  <ul>
  <li>Global error handling</li>
  <li>No need to catch errors in either vuex or component</li>
  <li>No boiler-plate code</li>
  </ul>
  
  <p><strong>CONS</strong></p>
  
  <ul>
  <li>All exceptions are unhandled, meaning non-axios errors are uncaught.</li>
  </ul>
  
  <hr>
  
  <p><strong>Alternative 4 -</strong> <em>Custom error plugin</em></p>
  
  <p>I've been experimenting in implementing a custom plugin that catches all exceptions, but I'm not succeeding in making it work.</p>
  
  <p><em>in</em> <strong><em>plugins/catch.js:</em></strong></p>
  
  <pre><code>export default (ctx, inject) =&gt; {
      const catchPlugin = function (func) {
          return async function (args) {
              try {
                  await func(args)
              } catch (e) {
                  return console.error(e)
              }
          }
      };
      ctx.$catch = catchPlugin;
      inject('catch', catchPlugin);
  }
  </code></pre>
  
  <p><em>in</em> <strong><em>pages/login.vue:</em></strong></p>
  
  <pre><code>export default {
      methods: {
          onLogin: this.$catch(async function () {
              await this.$store.dispatch('auth/login', { email: this.email, password: this.password });
              this.$router.push('/home');
          }),
      },
  }
  </code></pre>
  
  <p><strong>PROS</strong></p>
  
  <ul>
  <li>No boilerplate.</li>
  <li>All errors caught in plugin.</li>
  </ul>
  
  <p><strong>CONS</strong></p>
  
  <ul>
  <li>I cannot make it work. :(</li>
  </ul>
  
  <hr>
  
  <p>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?</p>
  
  <p>Thank you for your time!</p>