如何在 Vuex 操作完成之前阻止 Vue 生命周期继续? [英] How to stop Vue life cycle from moving on before Vuex actions have completed?

查看:81
本文介绍了如何在 Vuex 操作完成之前阻止 Vue 生命周期继续?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我想在应用程序的其余部分启动之前初始化 3 个 Vuex 模块.然而,无论我尝试什么,我执行初始化的 Vue 实例生命周期钩子中的代码在 3 个模块完成初始化之前继续运行.

In my application, I want to initialize 3 Vuex modules before the rest of the application starts. However, no matter what I try, the code in the Vue instance life cycle hook in which I perform the initialize, moves on before the 3 modules have completed their initialization.

我在执行初始化的 Vuex 操作中的代码周围添加了一个 promise,以便我可以(a)等待调用生命周期挂钩中的那些,但它不起作用.

I have added a promise around the code in the Vuex actions that do the initializing, so that I can (a)wait on those in the calling life cycle hook, but it doesn't work.

我查看了使用 Axios 的示例 Vuex 代码,我必须使我的代码与此类似,但没有成功.

I have looked at sample Vuex code that uses Axios, and I have to make my code similar to that, but without success.

我尝试使用Promise.all(...)"在beforeCreate"生命周期钩子中调用 init ,但仍然没有修复它.

I tried init call in the "beforeCreate" life cycle hook with "Promise.all(...)", but that still did not fix it.

我的主要 Vue 实例的代码如下所示:

The code of my main Vue instance looks like this:

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

Vuex 商店由 3 个模块组成,所有模块都有一个 'init' 操作.所有 3 个模块中的操作代码都是相同的.在下面的代码中有XXX"的地方,每个模块的调用都会略有不同;

The Vuex store consists of 3 modules, all of which have a 'init' action. The code of action in all 3 modules is the same. Where ever there is "XXX" in the code below, will be a slightly different call for each module;

  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 操作调用完全完成(即,直到所有承诺都已完成).

What I expect is that the "beforeCreate" code waits with moving on until the 3 init action calls have been fully completed (i.e. until all promises have been fulfilled).

我看到的是操作已启动(我在控制台中看到初始化开始..."日志).但后来我看到其中一个应用程序组件的 mount() 函数中的代码开始执行,这是不应该的,因为如果存储尚未完全初始化,它将无法正常工作.

What I see, is that the actions are started (I see the "Start of init..." log in the console). But then I see that code in the mounted() function of one of the applications components is started to execute, which it should not, as it will not work correctly if the store has not been fully initialized.

推荐答案

您不能通过使 async 暂停 beforeCreate.当您点击 await 时,它可能在内部看起来是暂停"的,但从外部角度来看,它只是返回一个承诺.Vue 不会注意到返回值,因此 promise 将被忽略并且生命周期将不间断地继续.您可以做的是在您的 data 中添加一些状态并对其进行操作以达到所需的效果:

You can't pause beforeCreate by making it async. It might appear to be 'paused' internally when you hit the await but from an external perspective it just returns a promise. Vue doesn't take any notice of the return value so the promise will be ignored and the life-cycle will continue uninterrupted. What you can do is add some state into your data and manipulate that to achieve the desired effect:

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中创建一个新的promise,你可以直接返回axios创建的链式promise.

Incidentally, you shouldn't need to create a new promise in init, you can just return the chained promise created by axios.

更新:

这是另一种方式,只是不要调用mount.

Here's another way, just holding back on calling mount.

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

这篇关于如何在 Vuex 操作完成之前阻止 Vue 生命周期继续?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆