等待 axios API 在 vuex 中调用完成,然后继续 vue-router guard

Wait for axios API call in vuex to finish before continuing vue-router guard

我有一个 django-rest-axios-vuejs 应用程序堆栈,我正试图在 vue-router.

中为其做一些事情

vue-router beforeEach 守卫中,我正在验证权限,这是通过检查 vuex 存储中名为 me 的对象中的内容来完成的。一切正常,除非我刷新页面。

确实刷新页面也会清除 vuex 存储,我的 beforeEach 尝试检查空存储中的 me 对象。

因此,如果商店中没有这个 me 对象,我想从 API 中获取它。 问题是它需要“一些时间”并且 hasPermission() 方法在 API 调用完成之前执行。

所以我尝试在 API 调用之前放置一个 await 关键字,但它不起作用。

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)
        })
    }
  }

我发现让它等待的唯一方法是执行以下操作:

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()
  }
})

使用一些 sleep() 方法使其等待“随机”(2 秒)时间。

我对 async await 的用法有点陌生所以.. 我缺少什么才能让 await store.dispatch('FETCH_ME') 工作?

提前致谢:)

我有一个具有类似逻辑的宠物项目。我没有使用 meta

async beforeEnter(to, from, next) {
   await store.dispatch('getUser')
   if (store.getters.user) return next()
    next('/login')
}

逻辑如下。如果用户已登录,浏览器中就会有一个 cookie,它会与 store.dispatch 一起发送。如果令牌有效,后端 returns 用户,即如果 getter returns 用户,则用户已登录。我认为您的逻辑应该相同

我终于找到了这个LINK,我以前没见过...

这让我可以像这样重写我的 FETCH_ME 动作:

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)
     })
   })
}

其中 SET_ME 是我已经拥有的突变:

SET_ME: (state, user) => {
  state.me = user
},

这最终对我的情况有用,在 router.beforeEach 守卫中这样做:

if (!store.state.me) await store.dispatch('FETCH_ME') 有效地等待 dispatch 操作完成。