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

Posted

技术标签:

【中文标题】异步api调用后如何使用vuex getter【英文标题】:How to use vuex getter after async api call 【发布时间】:2019-05-15 13:53:44 【问题描述】:

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

我创建了一个示例 sn-p 来说明我的意思。如您所见,getLastNameByName() 失败,因为state.persons 为空。奇怪的是,如果我在那个 getter 中打印 state.persons,它会在 api 调用之后打印数组。

预期的行为是 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>

【问题讨论】:

【参考方案1】:

setTimeout() 不返回等待对象。检查承诺:

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>

无论如何,直接处理对存储的异步调用不是正确的方法。我认为在这种情况下更好的解决方案是watch 存储状态或使用computed 属性。

【讨论】:

我的错,我以为我以这种方式正确地重现了我的问题。该示例现在确实可以正常工作,所以我想这是因为我的项目中的其他内容。您能否详细说明您建议的更好的解决方案?在state.persons 上设置一个观察者并调用该手表中的吸气剂?但是,问题是我需要在另一个操作中使用该 getter。【参考方案2】:

在 jsbin.com 上试过,改进很少,没问题:

<!DOCTYPE html>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Vue example</title>

<div id="app">
  <show-person
    :name="getLastName('John')"
  ></show-person>
</div>

<script src="https://unpkg.com/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex@3.0.1/dist/vuex.min.js"></script>

<script>
const store = new Vuex.Store(
  state: 
    persons: []
  ,

  getters: 
    getLastName: state => name => 
      return state.persons.length
        ? state.persons.find(element => 
            return element.name === name
          ).lastname
        : ''
    
  ,

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

  actions: 
    getPeople: ( commit ) => new Promise(res => 
      const data = [
        name: 'John', lastname: 'Smith',
        name: 'Sarah', account: 'Appleseed'
      ]
      setTimeout(() => 
        commit('setPersons', data)
        res()
      , 1000)
    )
  
)

const ShowPerson = 
  functional: true,
  render: (h, ctx) => h('p', ctx.props.name)


new Vue(
  store,
  el: '#app',

  components: 
    ShowPerson
  ,

  computed: 
    ...Vuex.mapGetters([
      'getLastName'
    ])
  ,

  methods: 
    ...Vuex.mapActions([
      'getPeople'
    ])
  ,

  created () 
    this.getPeople()
  
)
</script>

【讨论】:

以上是关于异步api调用后如何使用vuex getter的主要内容,如果未能解决你的问题,请参考以下文章

Vuex 在异步操作完成之前访问状态

如何在Vuex的getter函数中调用getter函数

如何从 Vuex 的另一家商店调用 getter?

测试调用 Getter 和 Mutations 的 Vuex 动作

如何使用来自另一个模块的模块内的 getter 进行 Vuex 状态

如何在 Store Vuex 中加载 DOM 之前调用 api?