actions
no Vuex são assíncronos. A única maneira de permitir que a função de chamada (iniciador da ação) saiba que uma ação está concluída - é retornando uma promessa e resolvendo-a mais tarde.
Aqui está um exemplo: myAction
retorna a Promise
, faz uma chamada http e resolve ou rejeita a Promise
última - tudo de forma assíncrona
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);
})
})
}
}
Agora, quando o componente Vue for iniciado myAction
, ele obterá esse objeto Promise e poderá saber se foi bem-sucedido ou não. Aqui está um código de amostra para o componente 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")
})
}
}
Como você pode ver acima, é altamente benéfico actions
retornar a Promise
. Caso contrário, não há como o iniciador de ações saber o que está acontecendo e quando as coisas estão estáveis o suficiente para mostrar algo na interface do usuário.
E uma última observação sobre mutators
- como você corretamente apontou, eles são síncronos. Eles mudam as coisas no state
e geralmente são chamados de actions
. Não há necessidade de misturar Promises
com mutators
, como a actions
alça que parte.
Edit: Minhas visões sobre o ciclo Vuex de fluxo de dados unidirecional:
Se você acessar dados como this.$store.state["your data key"]
em seus componentes, o fluxo de dados será unidirecional.
A promessa da ação é apenas informar ao componente que a ação está completa.
O componente pode obter dados da função de resolução de promessa no exemplo acima (não unidirecional, portanto, não recomendado) ou diretamente do $store.state["your data key"]
qual é unidirecional e segue o ciclo de vida dos dados vuex.
O parágrafo acima assume que o seu mutador usa Vue.set(state, "your data key", http_data)
, assim que a chamada http for concluída em sua ação.
Promise.reject()
.failed
mutador que definestate.foo.failed = true
, que o componente pode manipular. Não é necessário que a promessa seja passada ao componente para isso e, como bônus, qualquer outra coisa que queira reagir à mesma falha também pode ser feita na loja.{isLoading:true}
no meu estado, e, portanto, recorri às promessas. Suas preferências podem variar. No final do dia, nosso objetivo é escrever um código livre de problemas e de manutenção. A promessa de atingir esse objetivo ou o estado da vuex - é deixada para os desenvolvedores e equipes individuais decidirem.Apenas para obter informações sobre um tópico fechado: você não precisa criar uma promessa, o axios retorna uma:
Ref: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Exemplo:
Outro exemplo:
Outro exemplo com async-waitit
fonte
Ações
Componente
fonte
TL: DR; retornar promessas de suas ações somente quando necessário, mas DRY encadeando as mesmas ações.
Durante muito tempo, também pensei que as ações retornadas contradizem o ciclo Vuex do fluxo de dados unidirecional.
Porém, há CASOS DE BORDA onde o retorno de uma promessa de suas ações pode ser "necessário".
Imagine uma situação em que uma ação possa ser acionada a partir de 2 componentes diferentes e cada um lide com o caso de falha de maneira diferente. Nesse caso, seria necessário passar o componente de chamada como parâmetro para definir diferentes sinalizadores na loja.
Exemplo idiota
Página em que o usuário pode editar o nome de usuário na barra de navegação e na página / perfil (que contém a barra de navegação). Ambos acionam uma ação "alterar nome de usuário", que é assíncrona. Se a promessa falhar, a página deve exibir apenas um erro no componente do qual o usuário estava tentando alterar o nome de usuário.
Claro que é um exemplo idiota, mas não vejo uma maneira de resolver esse problema sem duplicar o código e fazer a mesma chamada em duas ações diferentes.
fonte
actions.js
home.vue
fonte