【问题标题】:Best Practice in Error Handling in Vuejs With Vuex and Axios使用 Vuex 和 Axios 在 Vuejs 中进行错误处理的最佳实践
【发布时间】:2018-07-17 08:11:12
【问题描述】:

我正在使用 Vuex + axios,我想知道处理 vuex + axios 错误的最佳实践。我现在正在做的是,当我使用 axios 请求并返回错误时,它将以突变形式提交并更新我的状态。我想要做的是,如果我的请求有响应错误,它将返回到我的组件,以便我可以更快地处理错误。

和 Angular 一样,有一个依赖注入,响应会返回到组件。

【问题讨论】:

    标签: vue.js axios vuex


    【解决方案1】:

    让我告诉你方法,我用于错误记录的方法是这样的。 这样你就可以通过代码来处理所有的 vue 错误了。

    window.onerror = function (message, source, lineno, colno, error) {
      /// what you want to do with error here
    };
    

    这是浏览器的全局错误处理程序。如果有任何错误未被发现,可以通过这个来处理。

    另外,如果你想处理你的错误。你可以这样做。

    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
          // when you throw error this will also fetch error.
           throw error;
      });
    

    如果你想在 vue 上寻找错误处理,你可以去。 https://vuejs.org/v2/api/#errorHandler

    Vue.config.errorHandler = function (err, vm, info) {
      // handle error
      // `info` is a Vue-specific error info, e.g. which lifecycle hook
      // the error was found in. Only available in 2.2.0+
    }
    

    让我给你一个使用 window.onerror 的链接

    https://github.com/stacktracejs/stacktrace.js/

    【讨论】:

      【解决方案2】:

      有你的蛋糕,也吃吧。假设您已经在使用interceptor...

      axios.interceptors.response.use(function (response) {
        return response;
      }, function (error) {
        store.commit('ERROR', error) // just taking some guesses here
        return Promise.reject(error) // this is the important part
      })
      

      这将使承诺拒绝返回给调用者,因此在您的组件中,类似于...

      axios.whatever(...).then(res => {
        // happy days
      }, err => {
        // oh noes!
      })
      

      【讨论】:

      • 是否总是需要在vuex中的Action里面使用axios来提交表单?或者我可以在我的组件中使用 axios,然后将数据传递给 vuex 中的 Action 进行变异?
      • @LordGrim 对不起,我真的不确定你在问什么。问题应该在你上面的帖子中,而不是在 cmets 中
      • 我在return Promise.reject(error) 遇到了Uncaught (in promise) TypeError: Cannot read property 'version' of undefined 错误
      • @MKatleast3 我建议你打开一个新问题。我的答案中没有这样的代码
      • @Phil 我是唯一看到return Promise.reject(error) // this is the important part的人吗?哈哈我应该导入Promise吗?
      【解决方案3】:

      我得出的结论是,它们并不总是存在处理错误的通用方法,因此它们必须以某种方式与上下文耦合。拥有单独的 api 文件是一件好事,但要通过上面提到的来调解这一点。 我有单独的 api 文件,我正在执行以下操作:

      //comments-api.js
      export default {
          get (url, handler){
              //return the promise to further possible chains
              return axios.get(url)
                  .then( response => handler.success(response.data) )
                  .catch( error => handler.serverDownOrUnexpected(error.response) )
          },
      }
      //comments.js - vuex module
      import $comments from './../../services/api/comments-api'
      ...
      actions: {
          $comments.get(url, {
              success: (data) => commit('success_handler', data),
              serverDownOrUnexpected: (error) => commit('unexpected', error)
              //so on...
          })
      }
      ...
      

      在这种方法中,每当我想更改某些错误的处理方式时,我必须只在一个地方进行更改,再加上解耦代码的好处。

      【讨论】:

        【解决方案4】:

        承诺的力量! (加上异步/等待)

        vue 方法(mycomponent.js)

        async YourAsyncMethod() {
            const payload = {key: "var"}
            const result = await axios
                .post('/your/api/endpoint', payload)
                .catch(e => {
                    console.log(e.message)
                });
        }
        
        yourMethod() {
            // start axios logic
            const payload = {key: "var"}
            axios
                .post('/your/api/endpoint', payload)
                .then(response => {
                    console.log(response.data)
        
                    // start state action logic
                    this.$store
                        .dispatch('yourAction', payload)
                        .then(add => {
                            console.log('success mutation!');
                        })
                        .catch(error => {
                            // error = Error object,
                            console.log('error mutation:',error.message);
                            console.log(error) // to se full error object
                        });
                })
                .catch(error => {
                    console.log('error axios request', error.data)
                });
        }
        

        带有状态动作 (store/actions.js)

        yourAction(){
            const some_logic = false;
            if (!some_logic) {
                // when return a Promisse.reject
                //you can get error with catch(e) from youtMethod
                return Promise.reject(new Error("Impressora já adicionada"))
            }
            context.commit('MUTATION_METHOD', payload);
        }
        

        用 axios

        http
            .post('/your/api/endpoint', payload)
            .then(response => {
                console.log(response.data)
            })
            .catch(error => {
                console.log('error', error.data)
            });
        

        【讨论】:

          【解决方案5】:

          你可以像这样使用事件总线

          import Vue from 'vue'
          
          export const EventBus = new Vue();
          

          然后触发错误

          axios.get(...)
            .catch(function (error) {
               EventBus.$emit('error', error)
            });
          

          【讨论】:

            【解决方案6】:

            我只是用catch。我在切换到 vuex 之前使用的是同样的东西。这可能是最通用且有据可查的解决方案,让我可以像以前一样继续将错误插入到组件的 html 中。它还让我继续使用我的 loading = true, loading = false html 动画。

            所以我最终得到了 3 个状态属性、数据、错误和加载。它似乎对我有用。你的旅费可能会改变。我也在使用 vuex 模块和命名空间,但这是一个没有它的简化示例

            //somevuexstore.js
            
            actions: {
            
            fetchData(context) {
            
                axios
                    .get("api/someendpoint")
                    .then(response => {
                        context.commit('loading')
                        context.commit('organizations', response.data)
            
                    }).catch(error => {
                        console.log(error.response.data.message || error.message)
                        context.commit('error', error)
                    });
            },
            
            mutations: {
            organizations(state, data) {
                return state.organization = data
            },
            
            error(state, data) {
                return state.error = data
            },
            
            loading(state) {
                return state.loading = false
            },
            
            state= {
            
            organization: [],
            error: '',
            loading: true
            }
            

            然后在我的 component.vue 中,它与我之前的做法非常相似,只是添加了计算属性。

            computed: {
            ...mapState({
                    getError: 'error',
                    getLoading: 'loading',
                    getAllOrg: 'organization',
            }),
            }
            
            mounted() {
                  this.$store.dispatch('fetchData')
            }
            

            我的 html 会是这样的。

            <tr v-for="value in getAllOrg" :key="value.id">
               <td>{{ value.id }}</td>
               <td>{{ value.email }}</td>
               <td>{{ value.name }}</td>
               <td>{{ value.['created-at'] | formatDate }}</td>
            </tr>
            

            我在适当的地方插入错误消息

            <div v-if="getError" class="error">
               <p>{{ getError }}</p>
            </div>
            

            对于加载动画,我使用vue spinners 包在适当的地方插入到 html 中。

            <div v-if="getLoading" style="height:37px;">
                <p>
                  <bar-loader class="custom-class" color="#c2c2c2" 
                  getLoading="getLoading" 
                  :width="130"></bar-loader>
               </p>
            

            【讨论】:

              【解决方案7】:

              在 Vuex 中添加“最后加载”状态,并观察 root 的变化。

              这可能看起来繁重而复杂,但它是合乎逻辑的并且可以很好地分离组件。

              奖励:您会立即知道您是否已加载数据并且尝试是否成功!

              【讨论】:

                【解决方案8】:

                现在可在 VUE 3 组合 API 中获得独特处理

                我们可以使用 AXIOS 拦截器作为documentation 来设置所需的配置,然后在 VUE 中

                import {onErrorCaptured, ref} from "vue";
                
                setup(){
                    let errors = ref(null)
                    onErrorCaptured((error)=>{
                         // checking for server response first
                         errors.value = error.response?Object.values(error.response.data)[0]:error.message
                    })
                    return{errors}
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-10-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-12-02
                  • 1970-01-01
                  相关资源
                  最近更新 更多