Магазин Vuex не обновляется при вызове из разрешения обещания

1

У меня есть массив, связанный с хранилищем данных vuex и отображаемый как вычисленное свойство через помощник mapGetters. Этот массив называется items, и я вызываю REST API, чтобы обновить его в created() hook компонента. Действие vuex, которое у меня есть для этого, возвращает обещание, к которому обращается API, и вызывающий мутатор (который обновляет массив items) до разрешения. Мое понимание обещаний говорит мне, что мой then вызовы должны безопасно происходить после того, как асинхронное действие завершается, но если я пытаюсь получить доступ items из резолюции обещания, он пуст, несмотря на массив, конечно, будучи населенным вызовом API. Почему это не работает, как я ожидаю?

Код целиком, но вот соответствующие части

Составная часть:

  computed: {
    ...mapGetters({
      items: 'allHistoryItems'
    }),
// ...
  created () {
    this.$store.dispatch('fetchList').then(console.log(this.items))
  }

Действие:

  fetchList: ({ commit }) => {
    return new Promise((resolve, reject) => {
      fetchList().then(response => {
        commit(types.FETCH_LIST, response.data)
        resolve(response)
      })
    })
  }

Я могу получить доступ к ответу API от компонента, но, как уже упоминалось, items пустые. Не реагирует ли реактивность до тех пор, пока не решит обещание?

  • 0
    Избегайте анти-паттерна конструктора обещаний - сказав это, как «Действие» меняет элементы? Я не вижу связи
  • 0
    аааа .then(console.log(this.items)) ... должно быть .then(() => console.log(this.items)) ... .then нужна функция в качестве аргумента, а не результат вызов console.log (который, кстати, не определен)
Показать ещё 3 комментария
Теги:
vue.js
vuex
promise

2 ответа

2
Лучший ответ

Короче

created () {
    this.$store.dispatch('fetchList').then(console.log(this.items))
}

Когда вызвано created, он выполняет:

this.$store.dispatch('fetchList')

затем сразу

console.log(this.items)

Нет ничего ждать, тогда, когда this.$store.dispatch('fetchList') решает, .then не называется, как .then(undefined)... потому что console.log(this.items) возвращает undefined

измените это на

created () {
    this.$store.dispatch('fetchList').then(() => console.log(this.items));
}

В качестве бонуса - удаление конструктора обещаний anti-pattern:

fetchList: ({ commit }) => fetchList() 
    .then(response => {
        commit(types.FETCH_LIST, response.data);
        return response;
    }
);
0

Я думаю, что ваша новая конструкция Promise просто избыточна. Inspec этот простой пример, если он делает то, что вы хотите:

var store = new Vuex.Store({
  state: {
    hero: []
  },
  mutations: {
    updateHero (state, payload) {

      state.hero = payload
    }
  },
  actions: {
    async loadHero ({commit}, payload) {
      var response = await fetch('https://swapi.co/api/people/1/')
      commit('updateHero', await response.json())
    }
  }
})

new Vue ({
  el: '#app',
  store,
  computed: {
    hero () {
      return this.$store.state.hero
    }
  },
  methods: Vuex.mapActions(['loadHero'])
})
[v-cloak] {
  display: none;
}
<div id="app">
  Hero name is: <span v-cloak>{{ hero.name }}</span><br>
  <button @click="loadHero">Load hero personal data</button>
</div>

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню