promise vue.js es6-promise state-management vuex

promise - Devolviendo promesas de acciones de Vuex



vue.js es6-promise (4)

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:

export const loginForm = ({commit},data) => { return axios.post(''http://localhost:8000/api/login'',data).then((response) => { console.log(response); commit(''logUserIn'',response.data.data); }).catch((error) => { commit(''unAuthorisedUser'',{ error:error.response.data }) }) };

Otro ejemplo:

addEmployee({ commit, state }) { return insertEmployee(state.employee).then(result => { commit(''setEmployee'', result.data); return result.data // resolve }).catch(err => { throw err.response.data // reject }); },

Recientemente comencé a migrar cosas de jQ a un marco más estructurado que es VueJS, ¡y me encanta!

Conceptualmente, Vuex ha sido un cambio de paradigma para mí, pero estoy seguro de que sé de qué se trata ahora, ¡y lo entiendo totalmente! Pero existen algunas pequeñas áreas grises, principalmente desde el punto de vista de la implementación.

Este creo que es bueno por diseño, pero no sé si contradice el cycle Vuex del flujo de datos unidireccional.

Básicamente, ¿se considera una buena práctica devolver un objeto prometedor (similar) de una acción? Los trato como envoltorios asíncronos, con estados de falla y similares, por lo que parece una buena opción para devolver una promesa. Por el contrario, los mutadores simplemente cambian las cosas y son estructuras puras dentro de una tienda / módulo.


actions en Vuex son asíncronas. 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 una Promise , realiza una llamada http y resuelve o rechaza la Promise más tarde, 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 su componente Vue inicia 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 muy beneficioso que las actions devuelvan una 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 los mutators : como acertadamente señaló, son sincrónicos. Cambian cosas en el state , y generalmente se llaman desde actions . No hay necesidad de mezclar Promises con mutators , ya que las actions manejan 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 de $store.state["your data key"] que es unidireccional y sigue el ciclo de vida de datos vuex.

El párrafo anterior supone que su mutador usa Vue.set(state, "your data key", http_data) , una vez que la llamada http se completa en su acción.


Comportamiento

ADD_PRODUCT : (context,product) => { return Axios.post(uri, product).then((response) => { if (response.status === ''success'') { context.commit(''SET_PRODUCT'',response.data.data) } return response.data }); });

Componente

this.$store.dispatch(''ADD_PRODUCT'',data).then((res) => { if (res.status === ''success'') { // write your success actions here.... } else { // write your error actions here... } })


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.