Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vuex: How to wait for action to finish?

Tags:

vue.js

vuex

I want to implement a login method. My code for it is :

login() {
  let user = {
    email: this.email,
    password: this.password
  };

  this.$store.dispatch('auth/login', user)
  console.log(this.$store.getters['auth/getAuthError'])
},

Where I reach the store and dispatch the login action.

the action in the store looks like this:

login(vuexContext, user) {
        return axios.post('http://localhost:8000/api/user/login', user)
        .then(res => {
            vuexContext.commit('setToken', res.data.token)
            vuexContext.commit('setUser', res.data, {root: true})
            localStorage.setItem('token', res.data.token)
            Cookie.set('token', res.data.token )
            this.$router.push('/')
        }).catch(err => {
            vuexContext.commit('setAuthError', err.response.data)
        })
    },

In the catch block, if an error happens, I update the state and set authError property to the error i get.

My problem is that, in the login method, the console.log statement is executed before the action is actually finished so that the authError property is the state has not been set yet. How to fix this issue ?

like image 319
Ayman Tarig Avatar asked Mar 26 '20 10:03

Ayman Tarig


People also ask

Can Vuex actions be async?

An action in Vuex is where you perform interaction with APIs and commit mutations. Such interactions are inherently asynchronous.

Do Vuex actions return a promise?

In Vuex actions are asynchronous. If an action is complete , there is no way to detect that. You can return a Promise to let the calling function know that the action is complete. In the below example myAction returns a Promise.

What is difference between mutation and action in Vuex?

Mutations are intended to receive input only via their payload and to not produce side effects elsewhere. While actions get a full context to work with, mutations only have the state and the payload .

Can I call action from mutation Vuex?

In Vuex, actions are functions that call mutations. Actions exist because mutations must be synchronous, whereas actions can be asynchronous. You can define actions by passing a POJO as the actions property to the Vuex store constructor as shown below. To "call" an action, you should use the Store#dispatch() function.


1 Answers

Your action is returning a promise so you can console after the promise has been resolved in then() block.

login() {
  let user = {
    email: this.email,
    password: this.password
  };

  this.$store.dispatch('auth/login', user).then(() => {
   console.log(this.$store.getters['auth/getAuthError'])
   // this.$router.push('/') // Also, its better to invoke router's method from a component than in a store file, anyway reference of a component may not be defined in the store file till you explicity pass it
  })
},

OR, you can make login an async function & wait for the action till promise returned by action has been resolved

async login() {
  let user = {
    email: this.email,
    password: this.password
  };

  await this.$store.dispatch('auth/login', user)
  console.log(this.$store.getters['auth/getAuthError'])
},
like image 164
Shivam Singh Avatar answered Oct 24 '22 04:10

Shivam Singh