Hör auf, async/await erzwingen zu wollen
Promises sind gerade so angesagt
Seit Anbeginn der Zeit führen Entwickler viele alberne Streitereien. Vom klassischen „Tabs vs. Spaces” bis zur zeitlosen „Mac vs. PC”-Debatte – wir sind gut darin, ablenkende Argumente zu finden.
Antworten: Linux und Spaces.
Der Kampf…?
Promises vs. Async/Await!
Moment, ist das ein Kampf? Das muss doch ein Kampf sein, oder? Über Callbacks sprechen wir ja gar nicht mehr?
Nein, es ist kein Kampf. Letztlich ist es einfach ein weiteres potenzielles Werkzeug in deinem Werkzeugkasten. Weil async/await jedoch nicht die gesamte Promise-Funktionalität ersetzt (insbesondere Promise.all, .race) ist es irreführend, es als Ersatz darzustellen.
Es gibt viele einflussreiche Personen, die diesen Irrglauben fördern, async/await sei der Promise-Ersatz, auf den alle gewartet haben.
Hinweis: Nein, nope und noch nicht einmal ansatzweise.
Eine kürzliche Ergänzung in VS Code treibt diese Voreingenommenheit voran. Wie @umaar tweetete:
Visual Studio Code can now convert your long chains of Promise.then()‘s into async/await! 🎊 Works very well in both JavaScript and TypeScript files. .catch() is also correctly converted to try/catch ✅ pic.x.com/xb39Lsp84V
— Umar Hansa (@umaar) September 28, 2018
Wenn du Promises hasst und diese Refactoring-Funktion willst, gebe ich dir keine Schuld.
Ich empfinde mit. Ich verstehe.
Ich war dort. 🤗
Ich habe Promises früher gehasst. Heute bin ich komplett umgeschwenkt. Promises sind großartig. Sie können dich dazu befähigen/ermutigen, Funktionskomposition auszunutzen.
Es gibt 2 Bereiche, auf die ich mich zuerst zu konzentrieren empfehle, um deine Promise-Technik zu verbessern.
#1: Benannte Funktionen!
Töte deine anonymen Methoden. Die Verwendung benannter Funktionen macht, dass Code sich wie Poesie deiner Anforderungen liest.
Schauen wir uns ein gängiges Beispiel an:
Eine HTTP-GET-Anfrage mit fetch stellen:
Anti-Pattern
// ❌ Using anonymous inline functions 💩fetch(url) .then(response => response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))) .then(response => response.text())Lösung: Benannte Methoden
// ✅ Clarity emerges: named functionsfetch(url) .then(checkResponse) .then(getText)
// Reusable general-purpose functionsfunction checkResponse(response) { return response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))}function getText(response) { return response.text()}Die Vorteile dieses Ansatzes werden immer offensichtlicher, je trockener dein Code wird.
Zusätzliche Ressourcen: Schau dir meine 1-Minuten-Videos zu basis Logging und fortgeschrittenem Debugging mit dieser Technik an.
#2: Einzelziel (Funktionen)
Es klingt täuschend präzise: Einzelziel.
Und doch ist es so subjektiv, willkürlich und sicher manchmal sogar bedeutungslos.
Interessanterweise berichten die meisten Entwickler, sie seien verdammt gut darin, ihren Code auf Einzelziel zu trimmen. Nicht verwunderlich: Sie berichten auch, großartige Fahrer zu sein!
Schauen wir uns ein Beispiel an, das der (unglaublich talentierte) Jake Archibald in seinem Async/Await-Artikel für die Google Developers-Seite vorstellt (Hinweis: 2024, Link entfernt).
// source: https://developers.google.com/web/fundamentals/primers/async-functionsfunction logInOrder(urls) { // fetch all the URLs const textPromises = urls.map(url => { return fetch(url).then(response => response.text()); });
// log them in order textPromises.reduce((chain, textPromise) => { return chain.then(() => textPromise) .then(text => console.log(text)); }, Promise.resolve());}Einzelziel?
Ich würde sagen: Nein. Was macht logInOrder?
- Durch eine Liste von
urlsloopen - Auf sie einen Inline-HTTP-GET anwenden:
- HTTP
fetch - Response-Text-Body zurückgeben
- Ein
.then(text => console.log(text))nach jedem Promise intextPromiseanhängen - Ergebnisse seriell ausgeben
Es gibt 5 anonyme Methoden, die in dieser einzelnen Funktion definiert sind. Wie Jake sogar selbst anmerkt, ist das .reduce zu komplex. Es macht keinen Sinn, nuancierte Mechanismen überall im Code von Hand zu schreiben. Anders ausgedrückt: Wir schreiben keine DOM-Erstellungs-Code mit endlosen document.createElement(), element.setAttribute() usw. Stattdessen wählen wir das beste Werkzeug aus vielen Optionen: Hilfs-/Utility-Funktionen, Bibliotheken oder Frameworks.
Lösung: Einzelziel-Funktionen
Beginne mit dem Extrahieren von Methoden…

Fahre fort, indem du das .reduce() und logPromise() durch ein Promise.all und ein ..map() ersetzt…

Zusammenfassung
Versuche, diese Techniken auf deinen eigenen Code anzuwenden! Dann tweete mir und lass mich wissen, wie es gelaufen ist. Oder wenn du Fragen oder Kommentare hast, melde dich ebenfalls!
Hilf mit, die #PromiseTruth zu verbreiten, und teile diesen Artikel. ❤️
