【问题标题】:Axios promise is not throwing error in vue methodAxios 承诺不会在 vue 方法中抛出错误
【发布时间】:2019-04-07 19:03:16
【问题描述】:

正如标题所说,我在 Vue 方法 getTodo 中捕获错误时遇到问题。
点击Set wrong url,然后点击Get Todo,可以看到store中出现了预期的错误,但是在Vue中getTodo的promise的then执行,没有错误。如果您选择设置正确的网址,那么它工作正常。 控制台日志应如下所示:

error on store  
error on vue

JavaScriptHTML 如下:

const store = new Vuex.Store({
    state: {
        todo: '',
        msg: '',
        url: 'https://jsonplaceholder.typicode.com/todos/test',
        correct: false
    },
    mutations: {
        setTodo(state, payload) {
            state.todo = payload;
        },
        setMsg(state, payload) {
            state.msg = payload;
        },
        setCorrect(state) {
            state.url = 'https://jsonplaceholder.typicode.com/todos/1';
            state.correct = true;
        },
        setIncorrect(state) {
            state.url = 'https://jsonplaceholder.typicode.com/todos/test';
            state.correct = false;
        }
    },
    actions: {
        getTodo({ state, commit }) {
            return axios.get(state.url)
                .then(response => {
                    console.log('success on store');
                    commit('setMsg', 'success on store');
                    commit('setTodo', response.data);
                })
                .catch(error => {
                    console.log('error on store');
                    commit('setMsg', 'error on store');
                });
        }
    }
})
new Vue({
    el: '#app',
    data: {
        message: ''
    },
    computed: {
        todo() {
            return store.state.todo;
        },
        msg() {
            return store.state.msg;
        },
        correctUrl() {
            return store.state.correct;
        }
    },
    methods: {
        getTodo() {
            store.dispatch('getTodo').then(() => {
                console.log('success on vue');
                this.message = 'success on vue'
            }).catch((e) => {
                console.log('error on vue');
                this.message = 'error on vue';
            });
        },
        setCorrect() {
            store.commit('setCorrect');
        },
        setIncorrect() {
            store.commit('setIncorrect');
        }
    }
})
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <div id="app">
        <p>{{ message }}</p>
        <p>{{ todo }}</p>
        <p>Correct url: {{ correctUrl }}</p>
        <button @click="getTodo">Get Todo</button>
        <button @click="setCorrect">Set correct url</button>
        <button @click="setIncorrect">Set incorrect url</button>
    </div>
    
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vuex@3.0.1/dist/vuex.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</body>

</html>

【问题讨论】:

    标签: javascript vue.js promise axios vuex


    【解决方案1】:

    getTodo 操作中捕获错误后,您需要重新抛出错误..

    actions: {
            getTodo({ state, commit }) {
                return axios.get(state.url)
                    .then(response => {
                        console.log('success on store');
                        commit('setMsg', 'success on store');
                        commit('setTodo', response.data);
                    })
                    .catch(error => {
                        console.log('error on store');
                        commit('setMsg', 'error on store');
                        throw error;
                    });
            }
    }
    

    const store = new Vuex.Store({
        state: {
            todo: '',
            msg: '',
            url: 'https://jsonplaceholder.typicode.com/todos/test',
            correct: false
        },
        mutations: {
            setTodo(state, payload) {
                state.todo = payload;
            },
            setMsg(state, payload) {
                state.msg = payload;
            },
            setCorrect(state) {
                state.url = 'https://jsonplaceholder.typicode.com/todos/1';
                state.correct = true;
            },
            setIncorrect(state) {
                state.url = 'https://jsonplaceholder.typicode.com/todos/test';
                state.correct = false;
            }
        },
        actions: {
            getTodo({ state, commit }) {
                return axios.get(state.url)
                    .then(response => {
                        console.log('success on store');
                        commit('setMsg', 'success on store');
                        commit('setTodo', response.data);
                    })
                    .catch(error => {
                        console.log('error on store');
                        commit('setMsg', 'error on store');
                        throw error;
                    });
            }
        }
    })
    new Vue({
        el: '#app',
        data: {
            message: ''
        },
        computed: {
            todo() {
                return store.state.todo;
            },
            msg() {
                return store.state.msg;
            },
            correctUrl() {
                return store.state.correct;
            }
        },
        methods: {
            getTodo() {
                store.dispatch('getTodo').then(() => {
                    console.log('success on vue');
                    this.message = 'success on vue'
                }).catch((e) => {
                    console.log('error on vue');
                    this.message = 'error on vue';
                });
            },
            setCorrect() {
                store.commit('setCorrect');
            },
            setIncorrect() {
                store.commit('setIncorrect');
            }
        }
    })
    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Page Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    
    <body>
        <div id="app">
            <p>{{ message }}</p>
            <p>{{ todo }}</p>
            <p>Correct url: {{ correctUrl }}</p>
            <button @click="getTodo">Get Todo</button>
            <button @click="setCorrect">Set correct url</button>
            <button @click="setIncorrect">Set incorrect url</button>
        </div>
        
            <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/vuex@3.0.1/dist/vuex.js"></script>
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    </body>
    
    </html>

    【讨论】:

    • 感谢您的回答,它按我的预期工作,但我还有两个问题。我将来使用这种方法可能会遇到问题吗?例如,如果我想构建嵌套 API 调用。第二个问题是关于在 axios 中使用 js promise 还是没有任何意义?
    • @hafer Re-throwing 承诺链中的错误是一种常见模式。您只需要确保链中后期的error is handled properly
    • 至于 axios,你知道它是基于 promise 的,而且它是一个设计良好的库,所以除非有一些迫切需要混合你自己的 promise,否则我会避免这样做,以免你在不知不觉中陷入某些 anti-pattern在这个过程中。
    猜你喜欢
    • 1970-01-01
    • 2020-04-01
    • 2018-10-29
    • 2018-02-19
    • 2016-02-26
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多