VueRouter wait for ajax is done

5.2k Views Asked by At

I am building SPA and the problem is checking if user is admin or not.

After Vue.auth.getUserInfo() I want to stop whole application and wait for API response, Vue.auth.user.isAdmin is always false because I don't have response from api...

Here is router.beforeEach

router.beforeEach((to, from, next) => {

   if(Vue.auth.user.authenticated == false) {
       Vue.auth.getUserInfo();
   }

   if(Vue.auth.user.isAdmin) {
      next({ name: 'admin.index' })
   } else {
      next({name: 'client.index'})
   }
}

Get user info method:

getUserInfo() {
    Vue.http.get('/api/me')
        .then(({data}) => {
            this.user = data;
        }, () => {
            this.logout();
        })
}
2

There are 2 best solutions below

0
On BEST ANSWER

Assuming the state of Vue.auth.user.isAdmin is managed within your Vue.auth.getUserInfo() logic, you can try a promise approach (untested):

getUserInfo() {
  return new Promise((resolve, reject) => {
    Vue.http.get('/api/me')
      .then(({data}) => {
        this.user = data;
        // Or, to use when consuming this within the then() method:
        resolve(data);
      }, () => {
        reject();
      })
  })
}

Then, when you consume it in your guard (https://router.vuejs.org/en/advanced/navigation-guards.html):

// A couple small auth/guard helper functions
function guardCheck(next) {
  if(Vue.auth.user.isAdmin) {
    next({ name: 'admin.index' })
  } else {
    next({name: 'client.index'})
  }
}
function guardLogout(next) {
  Vue.auth.user.logout()
    .then(() => {
      next({ name: 'home.index', params: { logout: success }})
    })
}

router.beforeEach((to, from, next) => {
  if(Vue.auth.user.authenticated === false && !to.matched.some(record => record.meta.isGuest)) {
    Vue.auth.getUserInfo()
      .then((user) => {
        guardCheck(next)
      })
      .catch(() => {
        // Not sure how your logout logic works but maybe...
        guardLogout(next)
      })
  } else {
     guardCheck(next)
  }
}
0
On

It is asynchronus request.

You have few options. 1. Move this function to vue-router and place your code:

   if(Vue.auth.user.authenticated == false) {
       Vue.auth.getUserInfo();
   }

   if(Vue.auth.user.isAdmin) {
      next({ name: 'admin.index' })
   } else {
      next({name: 'client.index'})
   }
}

in then() function of your request.

  1. Probably better for your learning curve - to modify your getUserInfo() to be promise based.

You will then have in your auth module something like:

var getUserInfo = new Promise((resolve,reject) => {
 Vue.http.get('/api/me')
        .then(({data}) => {
            this.user = data;
            resolve();
        }, () => {
            this.logout()
            reject();
        })
}

and in your router:

router.beforeEach((to, from, next) => {

   if(Vue.auth.user.authenticated == false) {
       Vue.auth.getUserInfo().then(()=>{
if(Vue.auth.user.isAdmin) {
      next({ name: 'admin.index' })
   } else {
      next({name: 'client.index'})
   }
});
   }


}

I don't have an editor with me so it can have some small issues but generally should work. Hope it helps!