web-dev-qa-db-ja.com

Vue.js:Nuxtエラー処理

Vuexでエラー処理を設定するために少し苦労しています。これを行うにはかなりの数の方法があり、適切なエラー処理に関するドキュメントはほとんどないようです。満足のいく解決策はまだ見つかっていませんが、4つの代替案を試しています。


代替1-コンポーネントのキャッチおよび処理エラー

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

instore/auth.js:

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

[〜#〜]長所[〜#〜]

  • うーん。

[〜#〜] cons [〜#〜]

  • エラーは処理されず、vuexに保存されません。
  • コンポーネントメソッドに多くのボイラープレートコードを導入します。

代替2-vuexでのキャッチおよび処理エラー

inpages/login.vue:

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

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

[〜#〜]長所[〜#〜]

  • エラーオブジェクトは、任意のコンポーネントからvuexでアクセスできます
  • レイアウトでリアクティブエラーコンポーネントを使用できます。これは、エラー状態が変化すると明らかになります。

[〜#〜] cons [〜#〜]

  • エラーの原因を追跡する方法があるかどうかはわかりませんが、どのコンポーネントからエラーがスローされたかはわかりません。

代替3-axiosインターセプターを使用したエラーのキャッチ

inplugins/axios.js:

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

inpages/login.vue:

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

instore/auth.js:

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

[〜#〜]長所[〜#〜]

  • グローバルエラー処理
  • Vuexやコンポーネントのエラーをキャッチする必要はありません
  • ボイラープレートコードなし

[〜#〜] cons [〜#〜]

  • すべての例外は処理されません。つまり、非axiosエラーは捕捉されません。

代替4-カスタムエラープラグイン

私はすべての例外をキャッチするカスタムプラグインの実装を実験してきましたが、それを機能させることに成功していません。

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

inpages/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');
        }),
    },
}

[〜#〜]長所[〜#〜]

  • 定型文はありません。
  • プラグインでキャッチされたすべてのエラー。

[〜#〜] cons [〜#〜]

  • 動かせない。 :(

私の印象は、vue/nuxtのエラー処理に関するドキュメントが不足していることです。誰かが4番目の選択肢を機能させることができますか?これは理想的でしょうか?他の選択肢はありますか?従来型とは何ですか?

お時間をいただきありがとうございます!

30
nomadoda

オプション#4が機能しない理由は、実行されない関数を返すためです。

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

使用法:

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

execute('myArgument');

ご覧のとおり、サンプルを機能させるには、内部関数も実行する必要があります。

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

しかし...コンポーネントのエラーを処理することは悪いことではないと思います。これはビューコンポーネントと密接に結びついているからです。たとえば、ログインコンポーネントについて考えてみましょう。最近見られるのは、ユーザー名/パスワードが正しくない場合にトーストメッセージを表示するグローバルエラーハンドラー(toastr)です。私の経験では、これは最良の動作ではありません。良い出発点ですが、エラーメッセージをコンポーネントの近くに追加して、問題の原因を正確に表示することをお勧めします。つまり、コンポーネント自体に常にエラー処理(UI関連)を追加する必要があります。

また、社内で同じ製品に取り組んでいる同僚たちと、この問題に取り組んでいます。 1つはエラー処理を追加する方法で、もう1つは追加しない方法です。私の意見では、唯一の解決策は、適切なエラー処理を常に追加するように開発者を教育することです。 async/awaitの構文はそれほど悪くありません。

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

conについて最後に1つ:エラーは処理されず、vuexに保存されません。。なぜこれが悪いのですか?エラーをグローバルに利用できるようにする必要がありますか?私が見るものたくさんは、コンポーネント自体でのみ使用されるvuexに多くの無駄な状態を入れている人々です。ローカルコンポーネントの状態であることは悪くありません。ログインに関するものなので、このエラーはログインコンポーネントでのみ認識されます。

1
Dieterg

各Vuexモジュールの状態でerrorキーを作成します。次に、特定のコンポーネントのエラーを関連するVuexモジュールにディスパッチします。次に、個別のVuexモジュールでエラーを監視するグローバルハンドラーを作成し、トリガーされた場合はエラーを表示します。

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

ConAlternative 2からアドレス指定するには、次のいずれかを実行できます

(a)コンポーネントの名前またはコンポーネントへの参照を渡すか、

(b)呼び出しを行ったコンポーネントの状態でエラーを永続化できます。次に、コンポーネントでエラーの有無を確認して表示できます。そのために、ボイラープレートの必要性を放棄するためにミックスインを使用できます。、

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 });
        });
    },
}
0
Justin Kahn