actions
dans Vuex sont asynchrones. La seule façon de faire savoir à la fonction appelante (initiateur de l'action) qu'une action est terminée - est de renvoyer une promesse et de la résoudre plus tard.
Voici un exemple: myAction
renvoie a Promise
, effectue un appel http et résout ou rejette le Promise
dernier - le tout de manière asynchrone
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);
})
})
}
}
Maintenant, lorsque votre composant Vue démarre myAction
, il obtiendra cet objet Promise et pourra savoir s'il a réussi ou non. Voici un exemple de code pour le composant 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")
})
}
}
Comme vous pouvez le voir ci-dessus, il est très avantageux actions
de renvoyer unPromise
. Sinon, il n'y a aucun moyen pour l'initiateur de l'action de savoir ce qui se passe et quand les choses sont suffisamment stables pour afficher quelque chose sur l'interface utilisateur.
Et une dernière note concernant mutators
- comme vous l'avez souligné à juste titre, ils sont synchrones. Ils changent des éléments dans le state
, et sont généralement appelés depuis actions
. Il n'y a pas besoin de mélanger Promises
avec mutators
, comme le actions
manche cette partie.
Edit: Mes vues sur le cycle Vuex du flux de données unidirectionnel:
Si vous accédez à des données comme this.$store.state["your data key"]
dans vos composants, le flux de données est unidirectionnel.
La promesse de l'action est seulement de faire savoir au composant que l'action est terminée.
Le composant peut soit prendre des données de la fonction de résolution de promesse dans l'exemple ci-dessus (non unidirectionnel, donc non recommandé), soit directement de $store.state["your data key"]
desquelles est unidirectionnel et suit le cycle de vie des données vuex.
Le paragraphe ci-dessus suppose que votre mutateur utilise Vue.set(state, "your data key", http_data)
, une fois que l'appel http est terminé dans votre action.
Promise.reject()
.failed
mutateur qui définitstate.foo.failed = true
, que le composant peut gérer. Il n'est pas nécessaire que la promesse soit transmise au composant pour cela, et en prime, tout ce qui veut réagir au même échec peut également le faire depuis le magasin.{isLoading:true}
dans mon état, et j'ai donc eu recours aux promesses. Vos préférences peuvent varier. À la fin de la journée, notre objectif est d'écrire du code sans encombrement et maintenable. La décision d'atteindre cet objectif ou l'état de vuex est laissée aux développeurs individuels et aux équipes.Juste pour une information sur un sujet fermé: vous n'avez pas à créer de promesse, axios en renvoie une lui-même:
Réf: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Exemple:
Un autre exemple:
Un autre exemple avec async-await
la source
Actions
Composant
la source
TL: DR; ne retournez les promesses de vos actions que lorsque cela est nécessaire, mais DRY enchaînant les mêmes actions.
Pendant longtemps, j'ai également pensé que le retour des actions contredit le cycle Vuex du flux de données unidirectionnel.
Mais, il existe des CAS EDGE où le retour d'une promesse de vos actions pourrait être "nécessaire".
Imaginez une situation où une action peut être déclenchée à partir de 2 composants différents, et chacun gère le cas d'échec différemment. Dans ce cas, il faudrait passer le composant appelant en tant que paramètre pour définir différents indicateurs dans le magasin.
Exemple stupide
Page où l'utilisateur peut modifier le nom d'utilisateur dans la barre de navigation et dans la page / profile (qui contient la barre de navigation). Les deux déclenchent une action "changer le nom d'utilisateur", qui est asynchrone. Si la promesse échoue, la page ne doit afficher qu'une erreur dans le composant à partir duquel l'utilisateur essayait de changer le nom d'utilisateur.
Bien sûr, c'est un exemple stupide, mais je ne vois pas de moyen de résoudre ce problème sans dupliquer le code et faire le même appel dans 2 actions différentes.
la source
actions.js
home.vue
la source