actions
in Vuex sind asynchron. Die einzige Möglichkeit, die aufrufende Funktion (Initiator der Aktion) wissen zu lassen, dass eine Aktion abgeschlossen ist, besteht darin, ein Versprechen zurückzugeben und es später zu lösen.
Hier ein Beispiel: myAction
Gibt a zurück Promise
, führt einen http-Aufruf durch und löst den Promise
späteren auf oder lehnt ihn ab - alles asynchron
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);
})
})
}
}
Wenn Ihre Vue-Komponente jetzt gestartet myAction
wird, erhält sie dieses Promise-Objekt und kann feststellen, ob es erfolgreich war oder nicht. Hier ist ein Beispielcode für die Vue-Komponente:
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")
})
}
}
Wie Sie oben sehen können, ist es sehr vorteilhaft actions
, a zurückzugeben Promise
. Andernfalls kann der Aktionsinitiator nicht wissen, was passiert und wann die Dinge stabil genug sind, um etwas auf der Benutzeroberfläche anzuzeigen.
Und noch ein letzter Hinweis zu mutators
- wie Sie zu Recht betont haben, sind sie synchron. Sie ändern Sachen in der state
und werden normalerweise von angerufen actions
. Es besteht keine Notwendigkeit, Promises
mit mutators
dem actions
Teil dieses Teils zu mischen .
Bearbeiten: Meine Ansichten zum Vuex-Zyklus des unidirektionalen Datenflusses:
Wenn Sie wie this.$store.state["your data key"]
in Ihren Komponenten auf Daten zugreifen , ist der Datenfluss unidirektional.
Das Versprechen der Aktion besteht nur darin, der Komponente mitzuteilen, dass die Aktion abgeschlossen ist.
Die Komponente kann entweder Daten aus der Versprechungsauflösungsfunktion im obigen Beispiel entnehmen (nicht unidirektional, daher nicht empfohlen) oder direkt von $store.state["your data key"]
dieser unidirektional sein und dem vuex-Datenlebenszyklus folgen.
Der obige Absatz setzt voraus, dass Ihr Mutator verwendet Vue.set(state, "your data key", http_data)
, sobald der http-Aufruf in Ihrer Aktion abgeschlossen ist.
Promise.reject()
.failed
Mutator auslösen, der festlegtstate.foo.failed = true
, mit dem die Komponente umgehen kann. Dafür muss das Versprechen nicht an die Komponente weitergegeben werden, und als Bonus kann alles andere , das auf denselben Fehler reagieren möchte, dies auch im Geschäft tun.{isLoading:true}
in meinem Bundesstaat vermeiden und griff daher auf Versprechen zurück. Ihre Vorlieben können variieren. Letztendlich ist es unser Ziel, übersichtlichen und wartbaren Code zu schreiben. Ob das Versprechen dieses Ziel erreicht oder der Vuex-Status, bleibt den einzelnen Entwicklern und Teams überlassen.Nur zur Information zu einem geschlossenen Thema: Sie müssen kein Versprechen erstellen, axios gibt eines selbst zurück:
Ref: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Beispiel:
Ein anderes Beispiel:
Ein weiteres Beispiel mit Async-Warten
quelle
Aktionen
Komponente
quelle
TL: DR; Geben Sie Versprechen von Ihren Aktionen nur zurück, wenn dies erforderlich ist, aber DRY verkettet dieselben Aktionen.
Lange Zeit habe ich auch gedacht, dass die Rückgabe von Aktionen dem Vuex-Zyklus des unidirektionalen Datenflusses widerspricht.
Es gibt jedoch EDGE-FÄLLE, in denen die Rückgabe eines Versprechens aus Ihren Handlungen möglicherweise "notwendig" ist.
Stellen Sie sich eine Situation vor, in der eine Aktion von zwei verschiedenen Komponenten ausgelöst werden kann und jede den Fehlerfall unterschiedlich behandelt. In diesem Fall müsste die Aufruferkomponente als Parameter übergeben werden, um verschiedene Flags im Speicher zu setzen.
Dummes Beispiel
Seite, auf der der Benutzer den Benutzernamen in der Navigationsleiste und auf der Profilseite (die die Navigationsleiste enthält) bearbeiten kann. Beide lösen eine Aktion "Benutzername ändern" aus, die asynchron ist. Wenn das Versprechen fehlschlägt, sollte auf der Seite nur ein Fehler in der Komponente angezeigt werden, von der der Benutzer den Benutzernamen ändern wollte.
Natürlich ist es ein dummes Beispiel, aber ich sehe keine Möglichkeit, dieses Problem zu lösen, ohne Code zu duplizieren und denselben Aufruf in zwei verschiedenen Aktionen auszuführen.
quelle
action.js
home.vue
quelle