简体   繁体   English

如何处理 vuex 调度响应?

[英]How can I handle a vuex dispatch response?

I'm raising the white flag and asking for suggestions even though I feel the answer is probably right in front of my face.即使我觉得答案可能就在我面前,我还是举起了白旗并寻求建议。

I have a login form that I am submitting to an api (AWS) and acting on the result.我有一个登录表单,我要提交给 api (AWS) 并根据结果采取行动。 The issue I am having is once the handleSubmit method is called, I am immediately getting into the console.log statement... which to no surprise returns dispatch result: undefined我遇到的问题是一旦调用了handleSubmit方法,我就会立即进入console.log语句......毫不奇怪返回dispatch result: undefined

I realize this is likely not a direct function of vue.js, but how I have the javascript set executing.我意识到这可能不是 vue.js 的直接功能,而是我如何执行 javascript 集。

Here is my login component:这是我的登录组件:

// SignInForm.vue

handleSubmit() {
    try {
        const {username, password} = this.form;

        this.$store.dispatch('user/authenticate', this.form).then(res => {
            console.log('dispatch result: ', res);
        });
    } catch (error) {
        console.log("Error: SignInForm.handleSubmit", error);
    }
},
...

Here is what my store is doing.这是我的商店正在做的事情。 I'm sending it to a UserService I've created.我将它发送到我创建的UserService Everything is working great.一切都很好。 I am getting the correct response(s) and can log everything out I need.我得到了正确的响应,并且可以记录我需要的所有内容。 The UserService is making an axios request (AWS Amplify) and returning the response. UserService发出 axios 请求 (AWS Amplify) 并返回响应。

// user.js (vuex store)

authenticate({state, commit, dispatch}, credentials) {
    dispatch('toggleLoadingStatus', true);

    UserService.authenticate(credentials)
        .then(response => {
            dispatch('toggleLoadingStatus', false);

            if (response.code) {
                dispatch("setAuthErrors", response.message);
                dispatch('toggleAuthenticated', false);
                dispatch('setUser', undefined);

                // send error message back to login component
            } else {
                dispatch('toggleAuthenticated', true);
                dispatch('setUser', response);

                AmplifyEventBus.$emit("authState", "authenticated");

                // Need to move this back to the component somehow
                //     this.$router.push({
                //         name: 'dashboard',
                //     });
            }

            return response;
        });
},
...

Where I'm getting stuck at is, if I have error(s) I can set the errors in the state, but I'm not sure how to access them in the other component.我遇到的问题是,如果我有错误,我可以在状态中设置错误,但我不确定如何在其他组件中访问它们。 I've tried setting the data property to a computed method that looks at the store, but I get errors.我尝试将data属性设置为查看商店的计算方法,但出现错误。

I'm also struggling to use vue-router if I'm successfully authenticated.如果我成功通过身份验证,我也很难使用 vue-router。 From what I've read I really don't want to be doing that in the state anyway -- so that means I need to return the success response back to the SignInForm component so I can use vue-router to redirect the user to the dashboard.从我读过的内容来看,我真的不想在状态下这样做——所以这意味着我需要将成功响应返回给SignInForm组件,以便我可以使用 vue-router 将用户重定向到仪表盘。

Yep.是的。 Just took me ~6 hours, posting to SO and then re-evaluating everything (again) to figure it out.只花了我大约 6 个小时,发布到 SO,然后(再次)重新评估所有内容以解决问题。 It was in fact, somewhat of a silly mistake.事实上,这是一个有点愚蠢的错误。 But to help anyone else here's what I was doing wrong...但是为了帮助其他人,我做错了……

// SignInForm.vue

async handleSubmit() {
    try {
        await this.$store.dispatch("user/authenticate", this.form)
            .then(response => {
                console.log('SignInForm.handleSubmit response: ', response);  // works

            if (response.code) {
                this.errors.auth.username = this.$store.getters['user/errors'];
            } else {
                this.$router.push({
                    name: 'dashboard',
                });
            }
        }).catch(error => {
            console.log('big problems: ', error);
        });
    } catch (error) {
        console.log("Error: SignInForm.handleSubmit", error);
    }
},
...

Here's my first mistake: I was calling from an async method to another method - but not telling that method to be async so the call(er) method response was executing right away.这是我的第一个错误:我从一个async方法调用另一个方法 - 但没有告诉该方法是async所以 call(er) 方法响应立即执行。 Here's the updated vuex store:这是更新后的 vuex 商店:

 // user.js (vuex store)

 async authenticate({state, commit, dispatch}, credentials) { // now async
    dispatch('toggleLoadingStatus', true);

    return await UserService.authenticate(credentials)
        .then(response => {
            console.log('UserService.authenticate response: ', response);  // CognitoUser or code

            dispatch('toggleLoadingStatus', false);

            if (response.code) {
                dispatch("setAuthErrors", response.message);
                dispatch('toggleAuthenticated', false);
                dispatch('setUser', undefined);
            } else {
                dispatch('toggleAuthenticated', true);
                dispatch('setUser', response);

                AmplifyEventBus.$emit("authState", "authenticated");
            }

            return response;
        });
},
...

My second error was that I wasn't returning the result of the method at all from the vuex store.我的第二个错误是我根本没有从 vuex 商店返回该方法的结果。

Old way:旧方式:

UserService.authenticate(credentials)

Better way:更好的方法:

return await UserService.authenticate(credentials)

Hope this saves someone a few hours.希望这可以为某人节省几个小时。 ¯_(ツ)_/¯ ¯_(ツ)_/¯

This works for Vue3:这适用于 Vue3:

export default {
    name: 'Login',
    methods: {
        loginUser: function () {
            authenticationStore.dispatch("loginUser", {
                email: 'peter@example.com',
            })
            .then(response => {
                if (response.status === 200) {
                    console.log('Do something')
                }
            });
        },
    },
}

In the store you can simply pass back the http response which is a promise.在商店中,您可以简单地传回 http 响应,这是一个承诺。

const authenticationStore = createStore({
    actions: {
        loginUser({commit}, {email}) {
            const data = {
                email: email
            };

            return axios.post(`/authentication/login/`, data)
                .then(response => {
                    toastr.success('Success')
                    return response
                })
        },

    }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM