actions
en Vuex son asíncronos. La única forma de permitir que la función de llamada (iniciador de la acción) sepa que una acción está completa es devolviendo una Promesa y resolviéndola más tarde.
Aquí hay un ejemplo: myAction
devuelve un Promise
, realiza una llamada http y resuelve o rechaza el Promise
posterior, todo de forma así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);
})
})
}
}
Ahora, cuando se inicia su componente Vue myAction
, obtendrá este objeto Promise y podrá saber si tuvo éxito o no. Aquí hay un código de muestra para el 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 puede ver arriba, es altamente beneficioso actions
devolver a Promise
. De lo contrario, el iniciador de acciones no puede saber qué está sucediendo y cuándo las cosas son lo suficientemente estables como para mostrar algo en la interfaz de usuario.
Y una última nota con respecto a mutators
- como acertadamente señaló, son sincrónicos. Cambian cosas en el state
, y generalmente se les llama desde actions
. No hay necesidad de mezclar Promises
con mutators
, como el actions
mango esa parte.
Editar: Mis puntos de vista sobre el ciclo Vuex del flujo de datos unidireccional:
Si accede a datos como this.$store.state["your data key"]
en sus componentes, entonces el flujo de datos es unidireccional.
La promesa de la acción es solo hacer que el componente sepa que la acción está completa.
El componente puede tomar datos de la función de resolución de promesa en el ejemplo anterior (no unidireccional, por lo tanto no se recomienda), o directamente desde el $store.state["your data key"]
cual es unidireccional y sigue el ciclo de vida de los datos vuex.
El párrafo anterior supone que su mutador utiliza Vue.set(state, "your data key", http_data)
, una vez que se complete la llamada http en su acción.
Promise.reject()
.failed
mutador que establecestate.foo.failed = true
, que el componente puede manejar. No es necesario que la promesa pase al componente para eso, y como beneficio adicional, cualquier otra cosa que quiera reaccionar ante el mismo fallo también puede hacerlo desde la tienda.{isLoading:true}
en mi estado y, por lo tanto, recurrí a Promises. Sus preferencias pueden variar. Al final del día, nuestro objetivo es escribir código libre de desorden y mantenible. Si la promesa logra ese objetivo, o el estado vuex, se deja a los desarrolladores individuales y a los equipos para decidir.Solo para obtener información sobre un tema cerrado: no tiene que crear una promesa, axios devuelve una:
Ref: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Ejemplo:
Otro ejemplo:
Otro ejemplo con async-await
fuente
Comportamiento
Componente
fuente
TL: DR; devolver promesas de sus acciones solo cuando sea necesario, pero SECO encadenando las mismas acciones.
Durante mucho tiempo también pensé que las acciones de retorno contradicen el ciclo Vuex del flujo de datos unidireccional.
Pero, hay CASOS DE EDGE en los que devolver una promesa de sus acciones podría ser "necesario".
Imagine una situación en la que una acción se puede activar desde 2 componentes diferentes, y cada uno maneja el caso de falla de manera diferente. En ese caso, uno tendría que pasar el componente llamante como parámetro para establecer diferentes indicadores en la tienda.
Ejemplo tonto
Página donde el usuario puede editar el nombre de usuario en la barra de navegación y en la página / perfil (que contiene la barra de navegación). Ambos desencadenan una acción "cambiar nombre de usuario", que es asíncrona. Si la promesa falla, la página solo debería mostrar un error en el componente desde el que el usuario intentaba cambiar el nombre de usuario.
Por supuesto, es un ejemplo tonto, pero no veo una manera de resolver este problema sin duplicar el código y hacer la misma llamada en 2 acciones diferentes.
fuente
actions.js
home.vue
fuente