Как дождаться завершения действия перед доступом к состоянию хранилища Vue?

#javascript #vue.js #nuxt.js #vuex

Вопрос:

У меня есть Vuejs/Nuxtjs приложение, в котором мне нужно получить доступ Vuex к магазину state после того, как он был изменен Vuex action . В настоящее время, когда я пытаюсь запустить action , а assignment затем получаю старое состояние, а не то, которое было обновлено позже action .

Как заставить код дождаться action завершения, а затем выполнить следующую инструкцию? Ниже приведен код, который у меня есть в настоящее время: Компонент Vuejs:

 <template>
  <div>
    <input v-model="formData.value" type="text">
    <button @click="performAction">
      Click Me
    </button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      formData: {
        value: '',
        returnValue: ''
      }
    }
  },
  methods: {
    performAction () {
      // Set the value within the Vuex Store
      this.$store.commit('modules/DataStore/populateData', this.formData.value)

      // Perform the Action
      this.$store.dispatch('modules/DataStore/getData').then(() => {
        console.log("AFTER COMPLETE ACTION")
      })

      // Assign the update value to the variable
      this.formData.returnValue = this.$store.state.modules.DataStore.data
    }
  }
}
</script>

<style>
</style>
 

Магазин Vuex:

 export const state = () => ({
  data:''
})

export const mutations = {
  populateData (state, data) {
    state.data = data
  }
}

export const actions = {
    getData ({ commit, state, dispatch }) {
        const headers = { 'Content-Type': 'application/json' }
        this.$axios
            .post('/getUrlData', state.data, { headers })
            .then((response) => {
                console.log("WITHIN RESPONSE")
                commit('populateData',response.data)
            })
            .catch((error) => {
                commit('populateData', 'Unable to obtain data, Error : '   error)
            })
    }
}
 

Ниже приведены вещи, которые я пробовал, и в данный момент ничего не работает:

  1. Я попробовал эту .then() функцию.
  2. Я пытался Async , await но и то и другое не работает

Любые предложения будут по-настоящему оценены. Заранее спасибо.

Комментарии:

1. Ваш код не будет ждать завершения асинхронной операции. Попробуйте добавить follwing this.formData.returnValue = this.$store.state.modules.DataStore.data внутри вычисляемого свойства.

2. попробовал асинхронность и ожидание, но оба не работают — что именно вы пробовали? Предположительно, они не работали, потому что использовались неправильно. В настоящее время вы вообще не связываете обещания по цепочке, поэтому код, очевидно, не будет их ждать.

Ответ №1:

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

 getData ({ commit, state, dispatch }) {
    const headers = { 'Content-Type': 'application/json' }
    return this.$axios  // now this promise will be returned and you can chain your methods together
        .post('/getUrlData', state.data, { headers })
        .then((response) => {
            console.log("WITHIN RESPONSE")
            commit('populateData',response.data);
            return response.data; //this will allow you do send the data through to the next Then() call if you want to
        })
        .catch((error) => {
            commit('populateData', 'Unable to obtain data, Error : '   error)
        })
}
 

Этой ситуацией намного проще управлять с помощью ИМО с асинхронным ожиданием. Это становится:

 export const actions = {
    async getData ({ commit, state, dispatch }) {
        const headers = { 'Content-Type': 'application/json' }
        const response = await this.$axios.post('/getUrlData', state.data, { headers });
        console.log("WITHIN RESPONSE")
        commit('populateData',response.data);

     }
}
 

и

 methods: {
async performAction () {
    // Set the value within the Vuex Store
    this.$store.commit('modules/DataStore/populateData', this.formData.value)

     // Perform the Action
     await this.$store.dispatch('modules/DataStore/getData');
     console.log("AFTER COMPLETE ACTION");

    // Assign the update value to the variable
    this.formData.returnValue = this.$store.state.modules.DataStore.data
   }
}
 

Комментарии:

1. Большое спасибо за ответ. Это работает, как и ожидалось, но с одной небольшой проблемой. Когда я присваиваю значение своей переменной компонента this.formData.returnValue = this.$store.state.modules.DataStore.data , я получаю сообщение об ошибке client.js:227 Error: [vuex] do not mutate vuex store state outside mutation . Если я прокомментирую эту строку, то все будет работать так, как ожидалось. Я хотел знать, как я могу временно назначить состояние vuex моей переменной компонента?

Ответ №2:

Вы можете создать геттер в vuex :

 export const getters = {
  getData: (state) => state.data,
};
export const actions = {
  async setData ({ commit }, data) {
    const headers = { 'Content-Type': 'application/json' }
    await this.$axios
      .post('/getUrlData', data, { headers })
      .then((response) => {
        console.log("WITHIN RESPONSE")
        commit('populateData',response.data)
      })
      .catch((error) => {
        commit('populateData', 'Unable to obtain data, Error : '   error)
      })
  }
}
 

затем в компоненте вы можете сопоставить получатели и действия и вызвать их :

 import { mapGetters, mapActions } from 'vuex'

computed: {
...mapGetters(['getData']),
},
methods: {
  ...mapActions(['performAction']),
 
  async performAction() {
    await this.setData(this.formData.value)
    this.formData.returnValue = this.getData
  }
}