actions
w Vuex są asynchroniczne. Jedynym sposobem, aby powiadomić funkcję wywołującą (inicjatora akcji), że akcja została zakończona - jest zwrócenie obietnicy i rozpatrzenie jej później.
Oto przykład: myAction
zwraca a Promise
, wykonuje wywołanie http i rozwiązuje lub odrzuca Promise
późniejsze - wszystko asynchronicznie
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);
})
})
}
}
Teraz, gdy Twój komponent Vue zostanie zainicjowany myAction
, otrzyma ten obiekt Promise i będzie mógł wiedzieć, czy się powiodło, czy nie. Oto przykładowy kod komponentu 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")
})
}
}
Jak widać powyżej, actions
zwrot pliku Promise
. W przeciwnym razie inicjator akcji nie będzie wiedział, co się dzieje i kiedy sytuacja jest na tyle stabilna, aby wyświetlić coś w interfejsie użytkownika.
I ostatnia uwaga dotycząca mutators
- jak słusznie zauważyłeś, są one synchroniczne. Zmieniają rzeczy w state
i zwykle są wywoływani z actions
. Nie ma potrzeby mieszania Promises
z tą częścią mutators
jak actions
uchwyt.
Edycja: Moje poglądy na cykl Vuex jednokierunkowego przepływu danych:
Jeśli uzyskujesz dostęp do danych, tak jak this.$store.state["your data key"]
w swoich komponentach, przepływ danych jest jednokierunkowy.
Obietnicą działania jest jedynie poinformowanie komponentu, że działanie jest zakończone.
Komponent może albo pobierać dane z funkcji obietnicy rozwiązania w powyższym przykładzie (nie jednokierunkowe, dlatego nie jest zalecane) lub bezpośrednio, z $store.state["your data key"]
której jest jednokierunkowy i podąża za cyklem życia danych vuex.
Powyższy akapit zakłada, że Twój mutator używa Vue.set(state, "your data key", http_data)
, gdy wywołanie http zostanie zakończone w Twojej akcji.
Promise.reject()
.failed
mutator, który ustawiastate.foo.failed = true
, z którym komponent może sobie poradzić. Nie potrzeba obietnicy być przekazywane do komponentu o tym, i jako bonus, coś innego , że chce, aby reagować na tej samej awarii można zrobić ze sklepu też.{isLoading:true}
w moim stanie, dlatego skorzystałem z obietnic. Twoje preferencje mogą się różnić. Ostatecznie naszym celem jest napisanie kodu bez bałaganu i łatwego w utrzymaniu. To, czy obietnica osiągnie ten cel, czy stan vuex - zależy od indywidualnych programistów i zespołów.Tylko dla informacji na zamknięty temat: nie musisz tworzyć obietnicy, axios sam ją zwraca:
Odniesienie: https://forum.vuejs.org/t/how-to-resolve-a-promise-object-in-a-vuex-action-and-redirect-to-another-route/18254/4
Przykład:
Inny przykład:
Kolejny przykład z async-await
źródło
działania
Składnik
źródło
TL: DR; zwracaj obietnice z twoich działań tylko wtedy, gdy jest to konieczne, ale SUCHO łącząc te same działania.
Przez długi czas myślałem też, że powracające akcje są sprzeczne z cyklem Vuex jednokierunkowego przepływu danych.
Ale istnieją SPRAWY EDGE gdzie powrocie obietnicę od twoich działań może być „konieczne”.
Wyobraź sobie sytuację, w której akcję można wyzwolić z 2 różnych komponentów, a każdy z nich inaczej obsługuje przypadek awarii. W takim przypadku należałoby przekazać komponent wywołujący jako parametr, aby ustawić różne flagi w sklepie.
Głupi przykład
Strona, na której użytkownik może edytować nazwę użytkownika w pasku nawigacyjnym i na stronie / profile (która zawiera pasek nawigacyjny). Oba wyzwalają akcję „zmień nazwę użytkownika”, która jest asynchroniczna. Jeśli obietnica nie powiedzie się, strona powinna wyświetlać błąd tylko w komponencie, z którego użytkownik próbował zmienić nazwę użytkownika.
Oczywiście to głupi przykład, ale nie widzę sposobu rozwiązania tego problemu bez powielania kodu i wykonywania tego samego wywołania w 2 różnych akcjach.
źródło
działania.js
home.vue
źródło