在您发送了一个改变了状态的异步操作之后,在vuex中调用getter的正确方法是什么?

我创建了一个示例片段来说明我的意思.正如你所看到的,getLastNameByName()失败了,因为state.persons是空的.奇怪的是,如果我在getter中打印state.persons,它会在api调用后打印array.

预期的行为是getLastNameByName('John')返回{name: 'John', lastname: 'Smith'}

const store = new Vuex.Store({
  state: {
    persons: []
  },

  getters: {
    getLastNameByName: (state) => (name) => {

      // console.log(state.persons) returns the state, yet I cannot call .find on it 
      return state.persons.find(element => {
        return element.name === name
      }).lastname
    },
  },

  mutations: {
    setPersons: (state, payload) => {
      state.persons = [...payload]
    }
  },

  actions: {
    async getPeople({commit}) {
        return new Promise(function(resolve, reject) {
          setTimeout(async () => {
             commit('setPersons', [{
               name: 'John',
               lastname: 'Smith'
            }, {
            name: 'Sarah',
            account: 'Appleseed'
          }])

           resolve();
         }, 1000)
      })
  }
  }
})

new Vue({
  store,
  el: '#app',
  mounted() {
    this.$store.dispatch('getPeople').then( () =>  { 
      console.log(this.$store.getters.getLastNameByName('John'))
    })
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuex"></script>

<div id="app">
</div>

推荐答案

setTimeout()不返回可等待的对象.promise 判断:

const store = new Vuex.Store({
  state: {
    persons: []
  },

  getters: {
    getLastNameByName: (state) => (name) => {
      return state.persons.find(element => {
        return element.name === name
      }).lastname
    },
  },

  mutations: {
    setPersons: (state, payload) => {
      state.persons = [...payload]
    }
  },

  actions: {
    async getPeople({commit}) {
        return new Promise(function(resolve, reject) {
          setTimeout(async () => {
             commit('setPersons', [{
               name: 'John',
               lastname: 'Smith'
            }, {
            name: 'Sarah',
            account: 'Appleseed'
          }])

           resolve();
         }, 1000)
      })
    }
  }
})

new Vue({
  store,
  el: '#app',
  mounted() {
    this.$store.dispatch('getPeople').then(() => {
       console.log(this.$store.getters.getLastNameByName('John'));
    })
  } 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuex"></script>

<div id="app">
</div>

无论如何,直接处理对store的异步调用不是一种合适的方式.我认为在这种情况下,更好的解决方案是watch个存储状态或使用computed个属性.

Vue.js相关问答推荐

如何默认打开一个v-list-group?

有没有办法将react 键作为值传递给由 v-for 创建的 v-model

如何将外部 svg 转换为 Vue3 组件?

在 onMounted 之前渲染的 Vue 模板

为什么普通对象在 Vue3 中自动变成响应式的?

如何将字符串中的
解析为 VUE.js 中的 html 标记

Vue:在表格中显示嵌套数据

运行vue-cli-service build --watch时没有 CSS 文件

如何在Typescript语言Vuejs中使用watch功能?

vue js 组件中的 this.$route 只返回 undefined

根据 URL 有条件地隐藏视图组件

Vue.js + Vuex:如何改变嵌套项状态?

自定义props类型

为什么 Vue.js 使用 VDOM?

从 vue.js 中的 store 获得的计算(computed)属性的设置器

如何在 Vue.js 应用程序中正确下载 Excel 文件?

异步api调用后如何使用vuex getter

Vue js在列表中添加动态字段,删除和排序不起作用

Vue - 重用方法的最佳方式

隐藏特定标题及其在 vuetify 数据表中的对应列