actions
в Vuex асинхронны. Единственный способ сообщить вызывающей функции (инициатору действия), что действие выполнено, - это вернуть Promise и разрешить его позже.
Вот пример: myAction
возвращает Promise
, выполняет http-вызов и разрешает или отклоняет более Promise
поздний - все асинхронно
actions: {
myAction(context, data) {
return new Promise((resolve, reject) => {
// Do something here... lets say, a http call using vue-resource
this.$http("/api/something").then(response => {
// http success, call the mutator and change something in state
resolve(response); // Let the calling function know that http is done. You may send some data back
}, error => {
// http failed, let the calling function know that action did not work out
reject(error);
})
})
}
}
Теперь, когда ваш компонент Vue запускается myAction
, он получит этот объект Promise и сможет узнать, удалось это или нет. Вот пример кода для компонента Vue:
export default {
mounted: function() {
// This component just got created. Lets fetch some data here using an action
this.$store.dispatch("myAction").then(response => {
console.log("Got some data, now lets show something in this component")
}, error => {
console.error("Got nothing from server. Prompt user to check internet connection and try again")
})
}
}
Как вы можете видеть выше, очень выгодно actions
вернуть домен Promise
. В противном случае у инициатора действия не будет возможности узнать, что происходит и когда все достаточно стабильно, чтобы что-то показать в пользовательском интерфейсе.
И последнее замечание относительно mutators
- как вы правильно заметили, они синхронны. Они меняют содержимое state
и обычно вызываются из actions
. Там нет необходимости смешивать Promises
с mutators
, как actions
справиться с этой частью.
Изменить: Мои взгляды на цикл Vuex однонаправленного потока данных:
Если вы this.$store.state["your data key"]
получаете доступ к данным, как в ваших компонентах, то поток данных будет однонаправленным.
Обещание действия состоит только в том, чтобы дать компоненту знать, что действие выполнено.
Компонент может либо получать данные из функции разрешения обещаний в приведенном выше примере (не однонаправленно, поэтому не рекомендуется), либо непосредственно из $store.state["your data key"]
которой является однонаправленным и следует жизненному циклу данных vuex.
В приведенном выше абзаце предполагается, что ваш мутатор использует Vue.set(state, "your data key", http_data)
после завершения http-вызова в вашем действии.
Promise.reject()
.failed
запускать мутатор, который устанавливаетstate.foo.failed = true
, с которым компонент может справиться. Нет необходимости в обещании не должны быть переданы в компонент для этого, и в качестве бонуса, все остальное , что хочет , чтобы реагировать на тот же провал может сделать это из магазина тоже.{isLoading:true}
в моем состоянии, и поэтому прибег к обещаниям. Ваши предпочтения могут отличаться. В конце концов, наша цель - написать простой и удобный в сопровождении код. Достигает ли обещание этой цели или состояние vuex - решать отдельным разработчикам и командам.Просто для информации по закрытой теме: вам не нужно создавать обещание, axios возвращает его сам:
Ссылка: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Пример:
Другой пример:
Другой пример с async-await
источник
действия
Составная часть
источник
TL: DR; возвращать обещания от ваших действий только тогда, когда это необходимо, но СУХОЙ цепочкой тех же действий.
Долгое время я также думал, что возвращаемые действия противоречат циклу Vuex однонаправленного потока данных.
Но есть КРАЙНЫЕ СЛУЧАИ, когда возврат обещания из ваших действий может быть «необходимым».
Представьте себе ситуацию, когда действие может быть инициировано двумя разными компонентами, и каждый по-своему обрабатывает случай сбоя. В этом случае необходимо передать вызывающий компонент в качестве параметра для установки разных флагов в магазине.
Тупой пример
Страница, на которой пользователь может редактировать имя пользователя на панели навигации и на странице / profile (которая содержит панель навигации). Оба инициируют действие «изменить имя пользователя», которое является асинхронным. Если обещание не выполняется, на странице должна отображаться ошибка только в том компоненте, с которого пользователь пытался изменить имя пользователя.
Конечно, это глупый пример, но я не вижу способа решить эту проблему без дублирования кода и выполнения одного и того же вызова в двух разных действиях.
источник
actions.js
home.vue
источник