How to prevent any routing before some async data (in Vuex store) has loaded?

Since this question was first asked, vue-router (v3.5.1) has exposed the ability to check for the initial navigation to perform operations like this and run on the first route only.

Compare from to VueRouter.START_LOCATION.

import VueRouter from 'vue-router'

const router = new VueRouter({
  // ...
})

router.beforeEach((to, from, next) => {
  if (from === VueRouter.START_LOCATION) {
    // initial navigation, handle Vuex initialization/hydration.
    initalizeOrWait().then((isLoggedIn) => {
      // handle navigation or pass to guard how it fits your needs here etc.
      next();
    });
  } else {
    next();
  }
})

The solution is simple. Add an init or equivalent Vuex action to the relevant parts of your store.
It should return a Promise of all the requests for data that your application absolutely needs*:

init ({ dispatch }) {       // Could also be async and use await instead of return
  return Promise.all([
    dispatch('getUserSession'), // Using another action
    dispatch('auth/init'),      // In another module
    fetch('tehKittenz')         // With the native fetch API
    // ...
  ])
}

The above code can use anything that returns a Promise.

Then just create a global navigation guard in your router using beforeEach.
This guard will wait on the promise generated by a dispatch to the store.

// In your router initialization code
const storeInit = store.dispatch('init')

// Before all other beforeEach
router.beforeEach((to, from, next) => {
  storeInit.then(next)
    .catch(e => {
      // Handle error
    })
})

This way, if routing happens before the store is fully loaded the router will simply wait.
If routing happens after, the promise will already be in a fulfilled state and routing will proceed.

Don't forget to use something like conditional rendering so as not to display a blank screen while routing is waiting on the data.


*: This will prevent all routing and navigation as long as the data is being fetched. Be careful.