最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin4浏览0评论

In my application I need some data to be loaded inside the VueX store before routing starts (for example user sessions).

An example of a race condition would be the following:

// In routes definition
{
  name: 'login',
  path: '/login',
  component: Login,
  meta: {
    goToIndexIf: () => store.getters['auth/loggedIn']
  }
}

In this situation the route guard might be executed before the user had been received from the server.

Using conditional rendering did not help as the route guards are executed with or without a <router-view v-if="storeReady"> within the rendered template.

How can I make all my routing wait on some asynchronous data?

In my application I need some data to be loaded inside the VueX store before routing starts (for example user sessions).

An example of a race condition would be the following:

// In routes definition
{
  name: 'login',
  path: '/login',
  component: Login,
  meta: {
    goToIndexIf: () => store.getters['auth/loggedIn']
  }
}

In this situation the route guard might be executed before the user had been received from the server.

Using conditional rendering did not help as the route guards are executed with or without a <router-view v-if="storeReady"> within the rendered template.

How can I make all my routing wait on some asynchronous data?

Share Improve this question asked Jul 24, 2018 at 9:45 KyllKyll 7,1398 gold badges44 silver badges64 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 11

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.

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

What i did and worked fine for me is wrapping my Vue instance (new Vue({... })) inside .then() "Promise".. this promise would resolve(null) if everything is fine and resolve an error when an errors occurs so i can render the vue instance conditionally based on the error

here i call my async function and wait until it loads the store and then initialize my app

my async function that uses the token to get me the data

doing so will allow the routes guards who work on the fetched store data to work properly

Hope that helps and sorry if my english is bad :)

发布评论

评论列表(0)

  1. 暂无评论