Warum Async-Await Arbeit mit setState Reagieren?
Ich habe mit async-await mit babel in meinem ReactJS Projekt. Ich entdeckte eine bequeme Nutzung mit setState Reagieren, ich würde es nur gerne besser verstehen. Betrachten Sie diesen code:
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value})
console.log('synchronous code')
}
changeAndValidate = async (e) => {
await this.handleChange(e)
console.log('asynchronous validation code')
}
componentDidUpdate() {
console.log('updated component')
}
Meine Absicht war, für die asynchrone Validierung code ausgeführt werden, nachdem die Komponente aktualisiert hat. Und es funktioniert! Die daraus resultierende console-log zeigt:
synchronous code
updated component
asynchronous validation code
Den Validierungs-code wird nur ausgeführt, nachdem handleChange hat aktualisiert den Zustand und den neuen Zustand wird gerendert.
In der Regel um code auszuführen, nachdem Status aktualisiert hat, Sie hätte ein callback zu verwenden.setState. Das bedeutet, wenn Sie ausführen möchten, alles nach handleChange, müssen Sie geben Sie eine callback-parameter, die dann an setState. Nicht schön. Aber in dem code-Beispiel, irgendwie erwarten weiß, dass handleChange ist abgeschlossen, nachdem der Status aktualisiert hat... Aber ich dachte, warten funktioniert nur mit Versprechungen und wartet auf ein Versprechen zu lösen, bevor Sie fortfahren. Es gibt kein Versprechen und keine Lösung in handleChange... Woher weiß er, was zu warten??
Die Implikation scheint zu sein, dass setState wird asynchron ausgeführt und warten ist irgendwie bewusst, wenn es abgeschlossen ist. Vielleicht setState verwendet verspricht intern?
Versionen:
reagieren: "^15.4.2"
babel-core: "^6.26.0"
babel-preset-env: "^1.6.0",
babel-preset-reagieren: "^6.24.1",
babel-preset-Stadium-0: "^6.24.1"
babel-plugin-system-import-Transformator: "^3.1.0",
babel-plugin-transform-Dekorateure-legacy: "^1.3.4",
babel-plugin-transform-Laufzeit: "^6.23.0"
await
auf undefined
(weil handleChange
nichts zurückgibt). Bist du sicher das es eine Auswirkung auf setState
?welche version von Reagieren und babel verwenden Sie?
das ist seltsam, aber ich bestätigen, erwarten Wirkung.
await this.setState({ data: true }, () => console.log('callback')); console.log('inline');
sagt ganz klar callback
wird gefeuert zunächst jedoch - entfernen Sie erwarten und arbeitet als Regel setState angenommen, um zu arbeiten - inline
ersten und dann callback
scheint richtig zu sein, sollten Sie schalten Sie ihn in eine Antwort wäre es hilfreich für andere, die in der Zukunft als auch dies ist eine ziemlich häufige Suche
Ich möchte gerne eine Ausarbeitung zu. Wird undefiniert zurückgegeben setState asynchron? Es tut immer wieder nach den updates?
InformationsquelleAutor Leo Fabrikant | 2017-10-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich habe versucht, mein bestes zu tun, zu vereinfachen und zu ergänzen Davin Antwort, so können Sie eine bessere Vorstellung davon bekommen, was ist hier eigentlich Los:
.handleChange, auf der rechten erwarten, ausführt:
2.1. setState führt er den updater aber da setState garantiert nicht unverzüglich zu aktualisieren es möglicherweise plant das update zu passieren, zu einem späteren Zeitpunkt (es spielt keine Rolle, ob es sofort oder zu einem späteren Zeitpunkt, alles was zählt ist, dass es geplant)
2.2. console.log('synchronous code') läuft...
2.3. .handleChange dann beendet, Rückkehr undefined ("undefined" zurückgibt, weil Funktionen undefined zurück, sofern nicht ausdrücklich etwas anderes angegeben ist)
erwarten dann nimmt diese undefined und da es nicht Versprechen, wandelt es in ein gelöst Versprechen, mit Versprechen.beheben(undefined) und wartet, bis es - es ist nicht sofort verfügbar, da hinter den kulissen, die es übergeben bekommt, um seine .dann Methode, die asynchron:
3.1. dies bedeutet, dass undefined erhalten, die in die Rückseite des Ereignis-queue, (was bedeutet, dass es jetzt hinter unserem setState-updater in die Ereignis-queue,...)
Ereignis-Schleife endlich erreicht und nimmt unsere setState update, das jetzt ausgeführt wird...
Ereignis-Schleife erreicht und nimmt undefined, die ausgewertet undefined (wir speichern könnte, wenn wir wollten, daher der = Häufig verwendet, vor warten, um zu speichern die korrigierte Ergebnis)
5.1. Versprechen.resolve() ist nun abgeschlossen, was bedeutet erwarten nicht mehr beeinflussen, so dass der rest der Funktion wieder aufnehmen kann,
Ich bin mir nicht sicher, es hängt von der Update-Algorithmus verwendet, kann nicht genug Informationen finden, aber, wenn Algorithmus Chargen-updates und führt Sie an das Ende des aktuellen Zyklus von der Ereignis-Schleife dann sollte es garantiert werden
So ist es nur Glück! 😀
InformationsquelleAutor linasmnew
Ich noch nicht getestet noch nicht, aber hier ist was ich denke passiert ist:
Den
undefined
zurückgegebenawait
ist in der Warteschlange nach dersetState
Rückruf. Dieawait
ist dabei einPromise.resolve
darunter (in derregenerator-runtime
), die wiederum Steuern Erträge auf das nächste Element auf der event-Schleife.So, es ist Zufall, dass die
setState
Rückruf passiert werden in der Warteschlange vor derawait
.Sie können dies testen, indem Sie ein setTimeout(f => f, 0) um die
setState
.regenerator-runtime
imbabel
ist im wesentlichen eine Schleife, die verwendetPromise.resolve
Ausbeute Kontrolle. Sie können sehen, das innere der _asyncToGenerator, es hat einePromise.resolve
.ist nicht handeln wie ein Versprechen.
await
ist gerade in der Warteschlange nach dersetState
Rückruf. Es ist nur eine event-loop.Ich meine, wenn Sie erwarten würde, bekommen in der Warteschlange vor der setState-callback?
Es hängt davon ab, wie/wenn die
setState
Rückruf in der Warteschlange befindet, die relativ zu der Rückkehr vonawait
. Aber mitawait
mitregenerator
generiert viel code, dass grundsätzlich ändert das async-flow (aber hoffentlich nicht das Verhalten).I dont ganz verstehen, weil ich noch nicht voll grokked die Ereignis-Schleife und wie die Ereignisse bekommen in der Warteschlange, aber dies scheint die logische Erklärung
InformationsquelleAutor Davin Tryon
Den
rv
oder Rückgabewert erwarten ist definiert als:So, da handleChange ist nicht ein asynchroner oder ein Versprechen Wert, es ist einfach wieder der Natürliche Wert (in diesem Fall gibt es keine Rückkehr, so
undefined
). Es gibt also keine async-Ereignis-Schleife "trigger" hier, "lassen Sie es wissen, handleChange ist fertig", es ist einfach nur läuft in der Reihenfolge, die Sie gegeben haben.InformationsquelleAutor Sterling Archer
Aber es kann hier der Fall sein.
Wenn Sie möchten, ersetzen Sie den Rückruf mit dem Versprechen, Sie können es selbst implementieren :
ref : https://medium.com/front-end-hacking/async-await-with-react-lifecycle-methods-802e7760d802
Vielleicht, weil es sofort aktualisiert, und funktioniert nicht, wenn es nicht der Fall ist.
Ich sehe, was du sagst, dass meine Methode funktioniert möglicherweise nicht, wenn setState entscheidet sich, zu warten. Könnte eine gute Idee sein, um dies zu testen. Aber setState ist dennoch mit seltsamen Verhalten. Ich will hinzufügen, ein weiteres Beispiel im original um dies zu demonstrieren.
it's not properly waiting for setState to complete. Your app just happens to finish setState quickly in that case, but will not for all cases
refIhre Benennung setStateAsync ist eher verwirrend... ist das nicht setState schon async ? Würde Sie Ihre Funktion besser benannt setStateSync, als die Absicht hier ist, um es so Aussehen sync.
InformationsquelleAutor Gabriel Bleu