Beherrschen der Versprechensaufhebung in JavaScript
Geschrieben von Rosario De Chiara✏️
In JavaScript sind Promises ein leistungsstarkes Tool zur Verarbeitung asynchroner Vorgänge, das besonders nützlich bei UI-bezogenen Ereignissen ist. Sie stellen einen Wert dar, der möglicherweise nicht sofort verfügbar ist, aber irgendwann in der Zukunft behoben wird.
Versprechen ermöglichen (oder sollten) Entwicklern, saubereren, besser verwaltbaren Code zu schreiben, wenn sie Aufgaben wie API-Aufrufe, Benutzerinteraktionen oder Animationen erledigen. Durch die Verwendung von Methoden wie .then(), .catch() und .finally() ermöglichen Promises eine intuitivere Möglichkeit, mit Erfolgs- und Fehlerszenarien umzugehen und die berüchtigte „Callback-Hölle“ zu vermeiden.
In diesem Artikel verwenden wir die neue Promise.withResolvers()-Methode (März 2024), mit der Sie saubereren und einfacheren Code schreiben können, indem Sie ein Objekt zurückgeben, das drei Dinge enthält: ein neues Promise und zwei Funktionen, eine zum Auflösen des Promise und die andere, um es abzulehnen. Da es sich um ein aktuelles Update handelt, benötigen Sie eine aktuelle Node-Laufzeitumgebung (v>22), um die Beispiele in diesem Artikel auszuführen.
Vergleich der alten und neuen JavaScript-Promise-Methoden
In den beiden folgenden funktional äquivalenten Codeabschnitten können wir den alten Ansatz und den neuen Ansatz vergleichen, der Methode zuzuweisen, ein Versprechen entweder aufzulösen oder abzulehnen:
let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); Math.random() > 0.5 ? resolve("ok") : reject("not ok");
Im Code oben sehen Sie die traditionellste Verwendung eines Promise: Sie instanziieren ein neues Promise-Objekt und müssen dann im Konstruktor die beiden Funktionen „resolve“ und „reject“ zuweisen, die wann aufgerufen werden benötigt.
Im folgenden Codeausschnitt wurde derselbe Codeabschnitt mit der neuen Promise.withResolvers()-Methode neu geschrieben und sieht einfacher aus:
const { promise, resolve, reject } = Promise.withResolvers(); Math.random() > 0.5 ? resolve("ok") : reject("not ok");
Hier können Sie sehen, wie der neue Ansatz funktioniert. Es gibt das Promise zurück, auf dem Sie die Methode .then() und die beiden Funktionen „resolve“ und „reject“ aufrufen können.
Der traditionelle Ansatz für Versprechen fasst die Erstellungs- und Ereignisverarbeitungslogik in einer einzigen Funktion zusammen, was einschränkend sein kann, wenn mehrere Bedingungen oder verschiedene Teile des Codes das Versprechen auflösen oder ablehnen müssen.
Im Gegensatz dazu bietet Promise.withResolvers() eine größere Flexibilität, indem es die Erstellung des Promises von der Auflösungslogik trennt, wodurch es für die Verwaltung komplexer Bedingungen oder mehrerer Ereignisse geeignet ist. Für einfache Anwendungsfälle kann die traditionelle Methode jedoch einfacher und vertrauter für diejenigen sein, die mit Standard-Versprechungsmustern vertraut sind.
Beispiel aus der Praxis: Aufrufen einer API
Wir können den neuen Ansatz nun an einem realistischeren Beispiel testen. Im folgenden Code sehen Sie ein einfaches Beispiel für einen API-Aufruf:
function fetchData(url) { return new Promise((resolve, reject) => { fetch(url) .then(response => { // Check if the response is okay (status 200-299) if (response.ok) { return response.json(); // Parse JSON if response is okay } else { // Reject the promise if the response is not okay reject(new Error('API Invocation failed')); } }) .then(data => { // Resolve the promise with the data resolve(data); }) .catch(error => { // Catch and reject the promise if there is a network error reject(error); }); }); } // Example usage const apiURL = '<ADD HERE YOU API ENDPOINT>'; fetchData(apiURL) .then(data => { // Handle the resolved data console.log('Data received:', data); }) .catch(error => { // Handle any errors that occurred console.error('Error occurred:', error); });
Die fetchData-Funktion ist so konzipiert, dass sie eine URL annimmt und ein Promise zurückgibt, das einen API-Aufruf mithilfe der Fetch-API verarbeitet. Es verarbeitet die Antwort, indem es prüft, ob der Antwortstatus im Bereich von 200–299 liegt, was auf einen Erfolg hinweist.
Bei Erfolg wird die Antwort als JSON geparst und das Promise mit den resultierenden Daten aufgelöst. Wenn die Antwort nicht erfolgreich ist, wird das Promise mit einer entsprechenden Fehlermeldung abgelehnt. Darüber hinaus umfasst die Funktion eine Fehlerbehandlung, um Netzwerkfehler abzufangen und das Promise abzulehnen, wenn ein solcher Fehler auftritt.
Das Beispiel zeigt, wie diese Funktion verwendet wird. Es zeigt, wie die aufgelösten Daten mit einem .then()-Block verwaltet und Fehler mithilfe eines .catch()-Blocks behandelt werden, um sicherzustellen, dass sowohl ein erfolgreicher Datenabruf als auch Fehler ordnungsgemäß verwaltet werden.
Im folgenden Code schreiben wir die Funktion fetchData() neu, indem wir die neue Methode Promise.withResolvers() verwenden:
function fetchData(url) { const { promise, resolve, reject } = Promise.withResolvers(); fetch(url) .then(response => { // Check if the response is okay (status 200-299) if (response.ok) { return response.json(); // Parse JSON if response is okay } else { // Reject the promise if the response is not okay reject(new Error('API Invocation failed')); } }) .then(data => { // Resolve the promise with the data resolve(data); }) .catch(error => { // Catch and reject the promise if there is a network error reject(error); }); return promise; }
Wie Sie sehen können, ist der obige Code besser lesbar und die Rolle des Objekts Promise ist klar: Die fetchData-Funktion gibt ein Promise zurück, das erfolgreich aufgelöst wird oder fehlschlägt, und ruft in jedem Fall die richtige Methode auf . Sie finden den Code oben im Repository mit dem Namen api.invocation.{old|new}.js.
Verspricht Stornierung
Der folgende Code untersucht, wie eine Promise-Stornierungsmethode implementiert wird. Wie Sie vielleicht wissen, können Sie ein Versprechen in JavaScript nicht stornieren. Versprechen stellen das Ergebnis eines asynchronen Vorgangs dar und sind so konzipiert, dass sie nach ihrer Erstellung aufgelöst oder abgelehnt werden, ohne dass ein integrierter Mechanismus zum Abbrechen vorhanden ist.
Diese Einschränkung entsteht, weil Promises einen definierten Zustandsübergangsprozess haben; Sie beginnen mit dem Status „Ausstehend“ und können, sobald sie erledigt sind, ihren Status nicht mehr ändern. Sie sollen das Ergebnis einer Operation kapseln und nicht die Operation selbst steuern, was bedeutet, dass sie den zugrunde liegenden Prozess nicht beeinflussen oder abbrechen können. Diese Designwahl hält Promises einfach und konzentriert sich auf die Darstellung des letztendlichen Ergebnisses einer Operation:
const cancellablePromise = () => { const { promise, resolve, reject } = Promise.withResolvers(); promise.cancel = () => { reject("the promise got cancelled"); }; return promise; };
In the code above, you can see the object named cancellablePromise, which is a promise with an additional cancel() method that, as you can see, simply forces the invocation of the reject method. This is just syntactic sugar and does not cancel a JavaScript Promise, though it may help in writing clearer code.
An alternative approach is to use an AbortController and AbortSignal, which can be tied to the underlying operation (e.g., an HTTP request) to cancel it when needed. From the documentation, you can see that the AbortController and AbortSignal approach is a more expressive implementation of what we implemented in the code above: once the AbortSignal is invoked, the promise just gets rejected.
Another approach is to use reactive programming libraries like RxJS, which offers an implementation of the Observable pattern, a more sophisticated control over async data streams, including cancellation capabilities.
A comparison between Observables and Promises
When speaking about practical use cases, Promises are well-suited for handling single asynchronous operations, such as fetching data from an API. In contrast, Observables are ideal for managing streams of data, such as user input, WebSocket events, or HTTP responses, where multiple values may be emitted over time.
We already clarified that once initiated, Promises cannot be canceled, whereas Observables allow for cancellation by unsubscribing from the stream. The general idea is that, with Observables, you have an explicit structure of the possible interaction with the object:
- You create an Observable, and then all the Observables can subscribe to it
- The Observable carries out its work, changing state and emitting events. All the Observers will receive the updates – this is the main difference with Promises. A Promise can be resolved just once while the Observables can keep emitting events as long as there are Observers
- Once the Observer is not interested in the events from the Observables, it can unsubscribe, freeing resources
This is demonstrated in the code below:
import { Observable } from 'rxjs'; const observable = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); }); const observer = observable.subscribe({ next(x) { console.log('Received value:', x); }, complete() { console.log('Observable completed'); } }); observer.unsubscribe();
This code cannot be rewritten with Promises because the Observable returns three values while a Promise can only be resolved once.
To experiment further with the unsubscribe method, we can add another Observer that will use the takeWhile() method: it will let the Observer wait for values to match a specific condition; in the code below, for example, it keeps receiving events from the Observable while the value is not 2:
import { Observable, takeWhile } from 'rxjs'; const observable = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); }); const observer1 = observable.subscribe({ next(x) { console.log('Received by 1 value:', x); }, complete() { console.log('Observable 1 completed'); } }); const observer2 = observable.pipe( takeWhile(value => value != "2") ).subscribe(value => console.log('Received by 2 value:', value));
In the code above, observer1 is the same as we have already seen: it will just subscribe and keep receiving all the events from the Observable. The second one, observer2, will receive elements from the Observable while the condition is matched. In this case, this means when the value is different from 2.
From the execution, you can see how the two different mechanisms work:
$ node observable.mjs Received by 1 value: 1 Received by 1 value: 2 Received by 1 value: 3 Observable 1 completed Received by 2 value: 1 $
Conclusion
In this article, we investigated the new mechanism to allocate a Promise in JavaScript and laid out some of the possible ways to cancel a Promise before its completion. We also compared Promises with Observable objects, which not only offer the features of Promises but extend them by allowing multiple emissions of events and a proper mechanism for unsubscribing.
LogRocket: Debug JavaScript errors more easily by understanding the context
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Try it for free.
Das obige ist der detaillierte Inhalt vonBeherrschen der Versprechensaufhebung in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Sowohl Python als auch JavaScripts Entscheidungen in Entwicklungsumgebungen sind wichtig. 1) Die Entwicklungsumgebung von Python umfasst Pycharm, Jupyternotebook und Anaconda, die für Datenwissenschaft und schnelles Prototyping geeignet sind. 2) Die Entwicklungsumgebung von JavaScript umfasst Node.JS, VSCODE und WebPack, die für die Entwicklung von Front-End- und Back-End-Entwicklung geeignet sind. Durch die Auswahl der richtigen Tools nach den Projektbedürfnissen kann die Entwicklung der Entwicklung und die Erfolgsquote der Projekte verbessert werden.

C und C spielen eine wichtige Rolle in der JavaScript -Engine, die hauptsächlich zur Implementierung von Dolmetschern und JIT -Compilern verwendet wird. 1) C wird verwendet, um JavaScript -Quellcode zu analysieren und einen abstrakten Syntaxbaum zu generieren. 2) C ist für die Generierung und Ausführung von Bytecode verantwortlich. 3) C implementiert den JIT-Compiler, optimiert und kompiliert Hot-Spot-Code zur Laufzeit und verbessert die Ausführungseffizienz von JavaScript erheblich.
