У меня есть массив, связанный с хранилищем данных 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
пустые. Не реагирует ли реактивность до тех пор, пока не решит обещание?
Короче
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;
}
);
Я думаю, что ваша новая конструкция 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>
.then(console.log(this.items))
... должно быть.then(() => console.log(this.items))
... .then нужна функция в качестве аргумента, а не результат вызов console.log (который, кстати, не определен)