48 votes

Vue.js : gestion des erreurs Nuxt

J'ai un peu de mal à mettre en place la gestion des erreurs avec vuex. Il semble y avoir plusieurs façons de le faire et peu de documentation sur la bonne gestion des erreurs. J'ai expérimenté quatre alternatives, mais je n'ai pas encore trouvé de solution satisfaisante.


Alternative 1 - Capture et traitement des erreurs sur le composant

sur 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
            });
        },
    },
}

sur 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

  • Les erreurs ne sont pas traitées et stockées dans Vuex.
  • Introduit beaucoup de code passe-partout dans les méthodes des composants.

Alternative 2 - Capture et traitement des erreurs en vuex

sur pages/login.vue :

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

sur 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

  • L'objet d'erreur est accessible avec vuex depuis n'importe quel composant
  • On pourrait utiliser un composant d'erreur réactif dans la mise en page, qui est révélé lorsque l'état d'erreur change.

CONS

  • Je ne suis pas sûr qu'il y ait un moyen de suivre la source de l'erreur, à partir de quel composant elle a été lancée.

Alternative 3 - Capture des erreurs à l'aide des intercepteurs axios

sur plugins/axios.js :

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

sur pages/login.vue :

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

sur store/auth.js :

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

PROS

  • Gestion globale des erreurs
  • Il n'est pas nécessaire d'attraper les erreurs dans Vuex ou dans le composant.
  • Pas de code passe-partout

CONS

  • Toutes les exceptions ne sont pas gérées, ce qui signifie que les erreurs non-axios ne sont pas attrapées.

Alternative 4 - Plugin d'erreur personnalisé

J'ai essayé d'implémenter un plugin personnalisé qui récupère toutes les exceptions, mais je ne parviens pas à le faire fonctionner.

sur 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);
}

sur 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

  • Pas de passe-partout.
  • Toutes les erreurs sont prises en compte dans le plugin.

CONS

  • Je n'arrive pas à le faire fonctionner. :(

Mon impression est qu'il y a un manque de documentation sur la gestion des erreurs dans vue/nuxt. Quelqu'un a-t-il réussi à faire fonctionner la quatrième solution ? Serait-ce l'idéal ? D'autres alternatives ? Qu'est-ce qui est conventionnel ?

Merci pour votre temps !

0 votes

Je pense que la méthode 3 concernant les intercepteurs axios est bonne pour gérer les erreurs de manière globale. stackoverflow.com/questions/35900230/

0 votes

Le meilleur moyen est d'utiliser middleware Document API

5voto

Dieterg Points 12111

La raison pour laquelle l'option 4 ne fonctionne pas est que vous renvoyez une fonction qui n'est jamais exécutée :

function catchPlugin(outerFunction) {
   return function async innerFunction(args) {
     try {
       const data = await outerFunction(args);
       return { data } 
     } catch (error) {
       return { error }
     }
   }
}

Utilisation :

const execute = catchPlugin((args) => {
  // do something
})

execute('myArgument');

Comme vous pouvez le constater, vous devez également exécuter la fonction interne pour que votre exemple fonctionne :

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

Mais... Je pense que la gestion des erreurs dans les composants n'est pas une mauvaise chose, puisque cela est étroitement couplé à votre composant de vue. Par exemple, pensez à un composant de connexion, ce que nous voyons de nos jours est un gestionnaire d'erreur global (toastr) qui affichera un message d'erreur si le nom d'utilisateur/mot de passe est incorrect. D'après mon expérience, ce n'est pas le meilleur comportement. C'est un bon point de départ, mais le mieux serait d'ajouter des messages d'erreur à proximité du composant pour indiquer ce qui s'est exactement passé. Cela signifie que vous devrez toujours ajouter la gestion des erreurs (liées à l'interface utilisateur) dans le composant lui-même.

Nous sommes également confrontés à ce problème dans notre entreprise avec des collègues travaillant sur le même produit. L'un ajoute la gestion des erreurs, l'autre non La seule solution, à mon avis, est d'éduquer les développeurs pour qu'ils ajoutent toujours une gestion d'erreur appropriée. La syntaxe avec async/await n'est pas si mal :

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

Une dernière chose à propos de votre con : Les erreurs ne sont pas traitées et stockées dans Vuex. . Pourquoi est-ce une arnaque ? Faut-il que l'erreur soit disponible dans le monde entier ? Ce que je vois beaucoup c'est que les gens mettent autant d'états inutiles dans vuex qui n'est utilisé que dans le composant lui-même. Il n'est pas mauvais d'avoir un état local du composant. Puisqu'il s'agit de connexion, cette erreur ne devrait être connue que dans le composant de connexion.

3voto

Adriano Resende Points 1152

Utilisez Promise sur action

Exemple en vuex :

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

En page :

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

0 votes

Ce n'est pas correct - toutes les actions dans Nuxt sont asynchrones, il n'y a donc pas besoin de l'envelopper à nouveau dans Promise.

0 votes

Il suffit de renvoyer l'appel à $get car elle renvoie déjà une promesse

1voto

Justin Kahn Points 596

Pour répondre à la Con de Alternative 2 vous pouvez soit

(a) passer dans le nom du composant ou même une référence au composant ou

(b) vous pouvez faire persister l'erreur dans l'état du composant qui a fait l'appel. Ensuite, dans votre composant, vous pouvez vérifier s'il y a une erreur et l'afficher. Pour cela, vous pouvez utiliser un mixin pour éviter d'avoir besoin d'une plaque de chaudière..,

dans le fichier 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 });
        });
    },
}

1voto

selfagency Points 349

Créer un error dans l'état de chaque module Vuex. Ensuite, envoyez l'erreur pour un composant donné à son module Vuex relatif. Créez ensuite un gestionnaire global pour surveiller les erreurs dans les différents modules Vuex et, si l'un d'eux est déclenché, affichez l'erreur.

// 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)
      }
    })
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X