在 VueRouter beforeEach 中使用 promised getter

Use promised getter in VueRouter beforeEach

我一直在努力使用从 vuex.actions 计算得出的 vuex.getters 作为 router.beforeEach 中的 if 语句。

这是我正在尝试做的事情:

  1. 每次用户进入网站时获取一组对象。

  2. 然后根据router.params.id使用array.find()定位同一个对象,以防用户直接进入站点url。

  3. 如果 router.params.id 不匹配对象数组中的任何 slug,则将路由重定向到 404。

这是我的方法

const router = new VueRouter(
  {
    routes: [
      {
        path: '/list/:id',
        name: 'list'
      },
      {
        path: '/edit/:id',
        name: 'edit'
      },
      //other routes
      {
        path: '/*',
        name: '404'
      }
    ]
  }
);
router.beforeEach((to, from, next)=>{

  if ( !store.state.lists.length ){
   // fetch Object Array when user first enter
    store.dispatch('fetchLists');

  }


  if ( to.name === 'list' || to.name === 'edit'){
    // limit route only 'list' & 'edit', preventing passing undefined params
      store.commit('cloneParams', to);

     // determine if currentMonth has a valid slug, if not go to 404
      store.getters.currentMonth.slug !== '' ? next() : next('/404');

  } else {

    next();
  }

});
getters: {
  currentMonth(state){
    var template = {
      month: '',
      slug: '',
      data: []
    }
    var obj = template;

    if ( state.lists.length ) {

      obj = state.lists.find(current => current.slug === state.paramsID);

      if ( obj === undefined ){
        obj = template
      }
    }

    return obj;
  },

actions: {
  fetchLists({commit}){
    axios('/lists').then(
      res=>{
        commit('storeList', res);
      }
    )
  },
mutations: {
  storeList(state, res){
    state.lists = res.data;
  },
  cloneParams(state, to){
    state.paramsID = to.params.id;
  },

但是,我发现 getter currentMonth 在获取对象数组 store.state.lists 并转到 404 后没有更新。同时它在 [=24 之后工作得很好=] 在用户转到此 SPA 的下一个其他页面时获取并存储。

路由守卫在检查 api 结果之前没有等待 http 请求完成。 Return 来自 fetchLists 的承诺:

actions: {
fetchLists({commit}){
  return axios('/lists').then(res => {          // return the promise
    commit('storeList', res);
  })
},

然后在导航守卫中等待那个承诺:

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

  if ( !store.state.lists.length ){
    await store.dispatch('fetchLists');         // Waiting for the promise
  }

  if ( to.name === 'list' || to.name === 'edit'){
    // limit route only 'list' & 'edit', preventing passing undefined params
      store.commit('cloneParams', to);

     // determine if currentMonth has a valid slug, if not go to 404
      store.getters.currentMonth.slug !== '' ? next() : next('/404');

  } else {
    next();
  }

});