Search code examples
vue.jsvuexrouter

ASync/Await is not working as expected in router.BeforeEach guard in vue?


this is my router guard :

router.beforeEach(async (to,from,next)=>{   
  await store.dispatch('GetPermission'); 
  if(to.matched.some(record => record.meta.requireAuth)){
    let permissions=store.state.permissions; //getting empty 
    console.log(permissions);
    if(permissions.filter(per => (per.name === 'read_list').length!=0)){
      next({
        path:'/dashboard/create'
      }) 
    }
    else{
        next()  
    }
  
  }
  // else if(to.matched.some(record => record.meta.requireAuth)){
  //     if(store.token!=null){
  //     next({
  //       path:'/dashboard'
  //     }) 
  //   }
  //   else{
  //     next()
  //   }
  // }
  else{
    next()
  }

});

problem is here though i m using await in dispatch method , i m not getting state value of permissions which is initially empty here is vuex store code :

GetPermission(context){
            axios.defaults.headers.common['Authorization']='Bearer ' + context.state.token
            axios.get('http://127.0.0.1:8000/api/user').then((response)=>{
                console.log(response)
                context.commit('Permissions',response.data.permission)
            })
//mutation:
Permissions(state,payload){
            state.permissions=payload
        }
//state
state:{
        error:'',
        token:localStorage.getItem('token') || null,
        permissions:'',
        success:'',
        isLoggedin:'',
        LoggedUser:{}
    }

help me to solve it please ??


Solution

  • actions in Vuex are asynchronous. The only way to let the calling function (initiator of action) to know that an action is complete - is by returning a Promise and resolving it later.

    Here is an example: myAction returns a Promise, makes a http call and resolves or rejects the Promise later - all asynchronously

    actions: {
    myAction(context, data) {
        return new Promise((resolve, reject) => {
            // Do something here... lets say, a http call using vue-resource
            this.$http("/api/something").then(response => {
                // http success, call the mutator and change something in state
                resolve(response);  // Let the calling function know that http is done. You may send some data back
            }, error => {
                // http failed, let the calling function know that action did not work out
                reject(error);
            })
        })
    }
    

    }

    Now, when your Vue component initiates myAction, it will get this Promise object and can know whether it succeeded or not. Here is some sample code for the Vue component:

    export default {
    mounted: function() {
        // This component just got created. Lets fetch some data here using an action
        this.$store.dispatch("myAction").then(response => {
            console.log("Got some data, now lets show something in this component")
        }, error => {
            console.error("Got nothing from server. Prompt user to check internet connection and try again")
        })
    }
    

    }

    Also,you are calling same route when no permission match, in that case it always call your same route and make infinite loop. Redirect to access denied page if permission denied.