Rückruf Hölle
Für JavaScript -Programmierer ist es gemütlich, Rückrufe zu behandeln, aber es ist nicht so schön, Rückrufe mit zu tiefen Levels zu behandeln. Der folgende Beispielcode-Snippet verwendet dreischichtige Rückrufe und füllt dann das Gehirn für weitere Schichten von Szenen auf. Es ist einfach sauer. Dies ist die legendäre Rückrufhölle.
getDirectories (Funktion (Dirs) {getFiles (Dirs [0], Funktion (Dateien) {getContent (Dateien [0], Funktion (Datei, Inhalt) {console.log ('Dateiname:', Datei); console.log (Inhalt);});});}); Funktion getDirectories (Callback) {setTimeout (function () {callback (['/home/ben']);}, 1000); setTimeout (function () {callback (Datei, 'Inhalt');}, 1000)}Lösung
Es gibt viele asynchrone Lösungen im Ökosystem, die das Problem der Callback -Hölle behandeln können, wie Bluebird, Q usw. Dieser Artikel konzentriert sich auf die Unterstützung der asynchronen Programmierung in der Spezifikation von ECMAScript 6/7.
ES6 Versprechen
Versprechen ist eine Lösung für asynchrones Programmieren und ein leistungsstarkes Tool, um das Problem der Rückrufhölle zu lösen.
Das Versprechen wurde im Jahr 2007 im JavaScript -Ökosystem als Mainstream angenommen, als das DOJO -Framework die Funktionalität von Dojo.Deferred hinzufügte. Mit der Popularität von Dojo.Derered schlug Kris Zyp im Jahr 2009 die CommonJS -Versprechen/eine Spezifikation vor. Anschließend erschien im Ökosystem eine große Anzahl von Versprechen -Implementierungen, darunter Q.Js, FuturesJs usw. Natürlich ist die Popularität von Versprechen hauptsächlich auf die Existenz von JQuery zurückzuführen, aber JQuery entspricht den CommonJS -Versprechen/einer Spezifikation nicht vollständig. Wie Sie sehen können, enthält die ES 6 -Spezifikation Versprechen.
Versprechen wird in MDN wie folgt beschrieben:
Das Versprechensobjekt ist ein Proxy für den Rückgabewert, der möglicherweise nicht bekannt ist, wenn das Versprechensobjekt erstellt wird. Sie können eine Handhabungsmethode zum Erfolg oder Misserfolg einer asynchronen Operation angeben. Dies ermöglicht es der asynchronen Methode, einen Wert wie eine synchrone Methode zurückzugeben: Die asynchrone Methode gibt einen enthaltenden ursprünglichen Rückgabewert zurück
Der folgende Code ist ein Beispiel im Abschnitt "Callback Hell", der durch Versprechen implementiert wird. Der Code sieht nicht sehr präzise aus, hat sich jedoch im Vergleich zu herkömmlichen hierarchischen Rückrufen erheblich verbessert, und der Code ist wartbar und lesbarer.
getDirectores (). Dann (Funktion (Dirs) {return get files (Dirs [0]);}). Dann (Funktion (Dateien) {return getContent (Dateien [0]);}). Dann (function (val) {console.log ('Filename:', val.file); console.log (val.content);};};}; Funktion getDirectories () {Neue Versprechen zurückgeben (Funktion (Resolve, Ablehnung) {setTimeout (function () {Resolve (['/home/ben']);}, 1000);});} Funktion GetFiles (Dir) {DIRR) return New Promise (Funktion (Resolve, Ablehnung) {SetTimeOut (Funktion () {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) {) '/test2.txt']);ES6 -Generator
Die Umsetzung von Versprechen ist nicht präzise genug, wir brauchen immer noch eine bessere Wahl, Co ist eine der Entscheidungen. CO ist ein asynchroner Durchflussregler, der auf Generator basiert. Bevor Sie CO verstehen, müssen Sie zuerst den Generator verstehen. Schüler, die mit C# vertraut sind, sollten alle verstehen, dass die C# 2.0 -Version das Keyword für Ertrag einführt, um den Generator zu iterieren. ES 6 -Generator ähnelt C#und verwendet auch Ertragssyntaxzucker und implementiert eine staatliche Maschine intern. Für eine bestimmte Verwendung finden Sie in der Abschnitt "MDN Dokument"* und finden Sie im Blog von Alloyteam-Team, um das generator eingehalten zu haben. Verwenden Sie CO, um den ES6 -Generator geschickt zu kombinieren, und ES6 verspricht, asynchrone Anrufe harmonischer zu machen.
co (function* () {var dirs = relief getDirectories (); var files = rufe get files (Dirs [0]); var contentVal = relief -getContent (Dateien [0]); console.log ('Dateiname:', contentVal.file); console.log (contentVal.content);});CO ist sehr clever und sein Kerncode kann das folgende Beispiel vereinfachen. Die allgemeine Idee ist es, rekursive Durchgangsgenerator zu verwenden, bis der Staat abgeschlossen ist. Natürlich tut CO mehr.
RUNGENERATOR (); function* run () {var dirs = rendite getDirectories (); var files = Ergeben Sie GetFiles (Dirs [0]); var contentVal = Ertrag getContent (Dateien [0]); console.log ('Dateiname:', contentVal.file); console.log (contentVal.Content);} Funktion RUNGenerator () {var gen = run (); Funktion Go (Ergebnis) {if (result.done) return; result.Value.then (Funktion (r) {go (gen.next (r));}); } go (gen.next ());}ES7 Async/wartet
ES6-Generator ist wirklich gut, aber schade, dass ich die Unterstützung einer Bibliothek von Drittanbietern brauche. Die gute Nachricht ist, dass ES 7 das Async/wartet Keyword ein, um das Problem asynchroner Anrufe perfekt zu lösen. Nun, .NET ist einen Schritt voraus, und .NET Framework 4.5 ist bereits der erste, der es unterstützt.
Der zukünftige Code wird so geschrieben:
run (); asynchrische Funktion run () {var dirs = warte getDirectories (); var files = erwartet GetFiles (Dirs [0]); var contentVal = warte GetContent (Dateien [0]); console.log ('Dateiname:', contentVal.file); console.log (contentVal.Content);}abschließend
Von der klassischen Callback-Asynchron-Programmiermethode bis zur Verbesserung der asynchronen Programmierung durch die ES6-Versprechenspezifikation bis zur eleganten Verarbeitung von mit dem ES-Generator und schließlich das perfekte Ende von ES7 Async/Warteding von ES7 Async/Wartee können wir verstehen, warum Ecmascript diese Merkmale und die Probleme aufweist, und die Entwicklung von Javascript Asynchrone und die Entwicklung von Javascript-Asynchrone.