Как остановить жизненный цикл Vue до завершения действий Vuex? - PullRequest
1 голос
/ 06 июля 2019

В моем приложении я хочу инициализировать 3 модуля Vuex до запуска остальной части приложения. Однако, что бы я ни пытался, код в хуке жизненного цикла экземпляра Vue, в котором я выполняю инициализацию, перемещается до того, как 3 модуля завершат свою инициализацию.

Я добавил обещание вокруг кода в действиях Vuex, которые выполняют инициализацию, чтобы я мог (а) ожидать тех, кто находится в вызывающем хуке жизненного цикла, но он не работает.

Я посмотрел пример кода Vuex, который использует Axios, и я должен сделать свой код похожим на это, но безуспешно.

Я пытался вызвать init в хуке жизненного цикла beforeCreate с Promise.all (...), но это все равно не помогло.

Код моего основного экземпляра Vue выглядит следующим образом:

new Vue({
  router,
  store,
  async beforeCreate() {
    await this.$store.dispatch('init')
  },
  render: h => h(App)
}).$mount('#app')

Хранилище Vuex состоит из 3 модулей, каждый из которых выполняет действие init. Код действия во всех 3 модулях одинаков. Где бы ни был "XXX" в приведенном ниже коде, вызов будет немного отличаться для каждого модуля;

  init: ({commit, dispatch}) => {
    return new Promise((resolve, reject) => {
      console.log('Start of init of XXX');
      Axios.get(`api/xxx`).then(response => {
        return response.data;
      }, error => {
        console.log('An error occured: ', error);
        reject(error);
      }).then(data => {
        const result = [];
        for (let key in data) {
          result.push(data[key]);
        }

        console.log('The API call resulted in ' + result.length + ' lines of code');

        resolve(result);
        commit('ADD_XXX', result);
      })
    })
  }

Я ожидаю, что код beforeCreate ожидает перехода, пока 3 вызова действия init не будут полностью завершены (т.е. пока все обещания не будут выполнены).

Что я вижу, так это то, что действия запускаются (я вижу в консоли журнал «Start of init ...»). Но затем я вижу, что код в функции mount () одного из компонентов приложения начинает выполняться, чего не должно быть, поскольку он не будет работать правильно, если хранилище не было полностью инициализировано.

1 Ответ

1 голос
/ 06 июля 2019

Вы не можете сделать паузу beforeCreate, сделав его async. Когда вы нажимаете await, это может показаться внутренне «приостановленным», но с внешней точки зрения оно просто возвращает обещание. Vue не обращает внимания на возвращаемое значение, поэтому обещание будет проигнорировано, и жизненный цикл будет продолжаться непрерывно. Что вы можете сделать, это добавить некоторое состояние в data и манипулировать им для достижения желаемого эффекта:

new Vue({
  router,
  store,
  data () {
    return {
      ready: false
    }
  },
  async beforeCreate() {
    await this.$store.dispatch('init')
    this.ready = true
  },
  render (h) {
     if (this.ready) {
       return h(App)
     }
  }
}).$mount('#app')

Кстати, вам не нужно создавать новое обещание в init, вы можете просто вернуть связанное обещание, созданное axios.

Обновление:

Вот еще один способ, просто сдерживать вызов mount.

new Vue({
  router,
  store,
  async beforeCreate() {
    await this.$store.dispatch('init')
    this.$mount('#app')
  },
  render: h => h(App)
})

...