I have a django-rest-axios-vuejs application stack for which I’m trying to do something in the vue-router
.
In the vue-router
beforeEach
guard, I’m verifying permissions and it is done by checking something in an object called me
in vuex store. Everything works well except when I refresh the page.
Indeed refreshing the page also clears vuex store and my beforeEach
tries to check the me
object from the store which is empty.
Therefore I’d like to fetch this me
object from the API if it isn’t in the store.
The problem is that it takes “some time” and the hasPermission()
method executes before the API call is finished.
So I tried to put a await
keyword before my API call but it doesn’t work.
My
beforeEach
guard :
router.beforeEach(async (to, from, next) => { const isLoggedIn = getIsLoggedIn() handleLoggedInStatus(isLoggedIn) if (to.meta.requiresAuth) { if (isLoggedIn) { if (to.meta.permission) { if (!store.state.me) await store.dispatch('FETCH_ME') hasPermission(to.meta.permission) ? next() : next({ name: 'HomePage' }) } else { next() } } else { next({ name: 'LoginForm' }) } } else { next() } })
My action from the store :
actions: { FETCH_ME: (state) => { http .get('base/users/me/') .then(response => { state.me = response.data }) .catch(error => { console.log(error) }) } }
The only way I’ve found to make it wait is to do the following :
function sleep (ms) { return new Promise(resolve => setTimeout(resolve, ms)) } router.beforeEach(async (to, from, next) => { const isLoggedIn = getIsLoggedIn() handleLoggedInStatus(isLoggedIn) if (to.meta.requiresAuth) { if (isLoggedIn) { if (to.meta.permission) { if (!store.state.me) { store.dispatch('FETCH_ME') await sleep(2000) } hasPermission(to.meta.permission) ? next() : next({ name: 'HomePage' }) } else { next() } } else { next({ name: 'LoginForm' }) } } else { next() } })
To make it wait a “random” (2 seconds) amount of time with a little sleep()
method.
I’m kinda new to the usage of async
await
so.. What am I missing to make await store.dispatch('FETCH_ME')
work ?
Thanks in advance 🙂
Advertisement
Answer
I finally found this LINK which I didn’t see before…
This allowed me to rewrite my FETCH_ME
action like this :
FETCH_ME ({ commit }) { return new Promise((resolve, reject) => { http .get('base/users/me/') .then(response => { commit('SET_ME', response.data) resolve() }) .catch(error => { console.log(error) reject(error) }) }) }
where SET_ME
is a mutation I already had :
SET_ME: (state, user) => { state.me = user },
Which is finally working for my case, where doing this in the router.beforeEach
guard :
if (!store.state.me) await store.dispatch('FETCH_ME')
effectively waits for the dispatch
action to finish.