webentwicklung-frage-antwort-db.com.de

Versprechen von Vuex-Aktionen einlösen

Ich habe kürzlich angefangen, Dinge von jQ auf ein strukturierteres Framework zu migrieren, nämlich VueJS, und ich liebe es!

Konzeptionell war Vuex für mich ein kleiner Paradigmenwechsel, aber ich bin zuversichtlich, dass ich weiß, worum es jetzt geht, und kann es voll und ganz verstehen! Aber es gibt ein paar kleine Grauzonen, hauptsächlich vom Standpunkt der Implementierung aus.

Dieser ist meiner Meinung nach von Natur aus gut, aber ich weiß nicht, ob er dem Vuex Zyklus eines unidirektionalen Datenflusses widerspricht.

Wird es als gute Praxis angesehen, ein versprechendes (ähnliches) Objekt aus einer Aktion zurückzugeben? Ich behandle diese als asynchrone Wrapper mit Versagenszuständen und Ähnlichem. Es scheint also eine gute Gelegenheit zu sein, ein Versprechen zurückzugeben. Im Gegensatz dazu ändern Mutatoren einfach Dinge und sind die reinen Strukturen innerhalb eines Geschäfts/Moduls.

89
Daniel Park

actions in Vuex sind asynchron. Die einzige Möglichkeit, der aufrufenden Funktion (dem Initiator der Aktion) mitzuteilen, dass eine Aktion abgeschlossen ist, besteht darin, ein Versprechen zurückzugeben und es später zu lösen.

Hier ist ein Beispiel: myAction gibt ein Promise zurück, führt einen http-Aufruf durch und löst das Promise später auf oder lehnt es 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 myAction initiiert, erhält sie dieses Promise-Objekt und kann feststellen, ob es erfolgreich war oder nicht. Hier ist ein Beispielcode für 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, wenn actions ein Promise zurückgibt. Andernfalls kann der Aktionsinitiator nicht wissen, was gerade passiert und wann die Dinge stabil genug sind, um etwas auf der Benutzeroberfläche anzuzeigen.

Und noch eine letzte Anmerkung zu mutators - wie Sie richtig betont haben, sind sie synchron. Sie ändern Dinge in state und werden normalerweise von actions aufgerufen. Es ist nicht erforderlich, Promises mit mutators zu mischen, da die actions diesen Teil behandeln.

Edit: Meine Ansichten zum Vuex-Zyklus des unidirektionalen Datenflusses:

Wenn Sie in Ihren Komponenten auf Daten wie this.$store.state["your data key"] Zugreifen, ist der Datenfluss unidirektional.

Das Versprechen von action ist nur, der Komponente mitzuteilen, dass die Aktion abgeschlossen ist.

Die Komponente kann entweder Daten aus der Funktion zum Auflösen von Zusagen im obigen Beispiel (nicht unidirektional, daher nicht empfohlen) oder direkt aus $store.state["your data key"] Beziehen, das unidirektional ist und dem vuex-Datenlebenszyklus folgt.

Im obigen Absatz wird davon ausgegangen, dass Ihr Mutator Vue.set(state, "your data key", http_data) verwendet, sobald der http-Aufruf in Ihrer Aktion abgeschlossen ist.

190
Mani

Nur für eine 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:

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
            })
        })
};

Ein anderes Beispiel:

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

Aktionen

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
  });
});

Komponente

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

TL: DR; Versprechen von Ihnen nur dann zurückgeben, wenn dies erforderlich ist, aber DRY dieselben Aktionen verketten.

Lange Zeit widersprach ich dem Vuex-Zyklus des unidirektionalen Datenflusses.

Aber es gibt Edge CASES, wo das Zurückgeben eines Versprechens aus Ihren Aktionen "notwendig" sein könnte.

Stellen Sie sich eine Situation vor, in der eine Aktion von zwei verschiedenen Komponenten ausgelöst werden kann und jede den Fehlerfall anders behandelt. In diesem Fall müsste man die Aufruferkomponente als Parameter übergeben, um verschiedene Flags im Store 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 die Seite nur einen Fehler in der Komponente anzeigen, von der aus der Benutzer versucht hat, den Benutzernamen zu ändern.

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.

0
srmico