Hallo Bernd,
danke für deine Antwort.
Du bekommst einen Promise von axios.post() und "catcht" den Fehler durch Angabe einer onRejected-Funktion. Dadurch gilt der Fehler erst einmal als behandelt, als wäre er nicht passiert.
Die onRejected-Funktion kann einen Alternativwert zurückgeben. Damit wird der neue, von then() zurückgegebene Promise resolved. Wenn dispatch und createFooFailure keine Exceptions auslösen, so wird der neue Promise immer resolved.
Ja, das warum habe ich mir schon erklären können. Meine Frage bezog sich darauf, wie ich damit am besten umgehe :-)
Wie kann man das verhindern? Indem man den Fehler nach der Behandlung noch einmal mit "throw" auslöst (rethrow).
let result; try { result = axios.post(...); dispatch(createFooSuccess(result)); } catch (e) { dispatch(createFooFailure(error)); throw error; } // Weiterer Code, der jetzt nur ausgeführt wird, wenn der POST erfolgreich war.
Bei Promises ist es ähnlich: Wenn man will, dass der neue Promise rejected wird, muss man im onRejected den "gefangenen" Fehler noch einmal "werfen".
function createFoo(foo) { return dispatch => { return axios.post("/foos", { foo }) .then( result => dispatch(createFooSuccess(result)), error => { dispatch(createFooFailure(error)); throw error; } ); }; }
Jetzt ist der neue, von then() erzeugte Promise im Erfolgsfalle resolved und im Fehlerfalle rejected.
Wenn du jetzt in einem anderen Action Creator obigen benutzt:
dispatch(createFoo(foo)).then( () => { dispatch(anotherActionCreator()); } );
Dann wird anotherActionCreator nur aufgerufen, wenn createFoo erfolgreich war.
Hm. Das ist eine gute Idee. Darauf bin ich tatsächlich nicht gekommen. Würdest rethrows empfehlen?
Wie gesagt, ich suche hier ausdrücklich nach den best practices. Mir fehlt bei SPAs im allgemeinen und React im speziellen noch die Erfahrung, um beurteilen zu können, welcher Weg der beste ist. Ich habe zwar gewisse Einblicke und Ideen, aber mangels Team fehlt mir der kritische Blick eines dritten 😉
Dieses "Rethrowing" kann man natürlich kapseln, sodass man es nicht ausdrücklich schreiben muss und nicht vergessen kann.
Wie würdest du das implementieren?
Ich könnte natürlich auch meine Redirections und dergleichen in die Actions verlagern und damit die Business-Logik komplett raushalten aus meinen Components… leider fehlt mir da noch etwas die Erfahrung um sagen zu können, was denn der Weg mit den wenigsten Nachteilen ist, um mit diesem Problem umzugehen.
Das ist der Weg, den ich empfehlen würde. Diese Logik ist m.M.n. in den Actions besser aufgehoben und dort auch einfacher zu testen. Durch redux-thunks Promise-Mechanismus können Async Action Creators einfach aufeinander aufbauen.
Ja, je mehr ich darüber nachdenke, desto mehr glaube ich das tatsächlich auch. Wie gehst du denn damit um, dass man ggfls Requests canceln will, etwa weil der User wild herumklickt und damit mehrere Actions auf einmal auslöst? Etwa fetchUsers
, fetchPosts
, fetchPost
und fetchComments
, in der Reihenfolge? In dem Fall könnte man fetchUsers
und fetchPosts
canceln.
Die Komponente muss dann auch einen High-Level Action Creator als prop bekommen.
Du meinst, dass ich den Action Creator weiter zerlege in kleinere, die nacheinander dispatcht werden und die Komponente dann nur den „Haupt-Action-Creator“ bekommt? Falls ja: ja, das war mein Gedanke dabei, die Business-Logik in die Actions zu verlegen.
LG,
CK