Promise.allSettled


Beim 71. Treffen von Ecma TC39 werden das Projekt und die Referenzimplementierung von Promise.allSettled , dem dritten der vier Hauptkombinatoren von Versprechungen, betrachtet.


Autoren : Jason Williams (BBC), Robert Pumley (Bloomberg), Matthias Binens (Google)
Meister : Matthias Binens (Google)
Stufe : 3


Für Fans von Podcasts, die auf YouTube dupliziert wurden.


Einführung und Motivation


In der Welt der Versprechen gibt es vier Hauptkombinatoren:


  • Promise.all . ES2015. Schließt beim ersten abgelehnten / abgelehnten Versprechen.
  • Promise.race . ES2015. Schließt beim ersten irgendwie gelösten / festgelegten Versprechen.
  • Promise.any . Stufe 1. Schließt beim ersten erfüllten / erfüllten Versprechen.
  • Promise.allSettled . Stufe 3 → Stufe 4. Wird nicht geschlossen.

Alle von ihnen sind in gewöhnlichen Benutzerbibliotheken weit verbreitet, jede von ihnen ist für sich nützlich und in verschiedenen Situationen geeignet.


Die Hauptanwendung dieses Kombinators tritt auf, wenn Sie eine Aktion unmittelbar nach Abschluss vieler Anforderungen ausführen möchten, unabhängig davon, ob sie erfolgreich waren oder fehlgeschlagen sind. Der Rest der Kombinatoren von Versprechungen ist geschlossen ( Kurzschluss ) und verwirft die Ergebnisse der Eingabewerte, die den Wettlauf um einen bestimmten Zustand des Systems verloren haben. Promise.allSettled ist insofern einzigartig, als es immer jeden erwartet, für den es verantwortlich ist.


Promise.allSettled gibt ein Versprechen zurück, das mit der Rückgabe einer Reihe von Schnappschüssen der Zustände der Versprechen ausgeführt wird, jedoch erst, nachdem absolut alle ursprünglichen Versprechen gelöst wurden.


Woher kommt der Name allSettled?


Wir sagen, dass ein Versprechen erfüllt wird, wenn es nicht bis zur Aussetzung ausgesetzt wird, d. H. wenn er entweder zufrieden oder abgelehnt ist - eines von zwei Dingen. Um die Terminologie zu verstehen, werfen Sie einen Blick auf das alte Dokument über Staaten und Schicksale .


Außerdem wird dieser Name, allSettled , häufig in vorhandenen Bibliotheken verwendet, die diese Funktionalität implementieren. Die Liste wird unten sein.


Beispiele


Stellen Sie sich vor, Sie müssen eine Reihe von Versprechungen durchlaufen und einen neuen Wert mit einem bekannten Status zurückgeben (der in einem der beiden möglichen Zweige der Logik auftritt).


 function reflect(promise) { return promise.then( (v) => { return { status: 'fulfilled', value: v }; }, (error) => { return { status: 'rejected', reason: error }; } ); } const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.all(promises.map(reflect)); const successfulPromises = results.filter(p => p.status === 'fulfilled'); 

Mit der vorgeschlagenen API kann der Entwickler diese Optionen verarbeiten, ohne die reflect Funktion unabhängig erstellen oder die Ergebnisse in temporären Variablen speichern zu müssen. Die neue API sieht folgendermaßen aus:


 const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const successfulPromises = results.filter(p => p.status === 'fulfilled'); 

Wenn wir aus irgendeinem Grund abgelehnte Versprechen brauchen, müssen wir wahrscheinlich die Gründe für das, was passiert ist, sammeln. allSettled macht dies genauso einfach.


 const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const errors = results .filter(p => p.status === 'rejected') .map(p => p.reason); 

Echte Beispiele


Sehr häufig ist der Wunsch zu wissen, dass alle Anforderungen abgeschlossen wurden, unabhängig vom Status der einzelnen Anforderungen. Dies ist wichtig, wenn Sie in Zukunft schrittweise Verbesserungen vornehmen möchten. Wir müssen nicht immer eine Antwort von der API erhalten.


 const urls = [ /* ... */ ]; const requests = urls.map(x => fetch(x)); // , -    ,  - - . //        ,   . try { await Promise.all(requests); console.log('  ,    .'); } catch { console.log('-    ,     . .'); } 

Mit Promise.allSettled Sie etwas schreiben, das unseren Erwartungen besser entspricht.


 //   ,     API  . Promise.allSettled(requests).finally(() => { console.log('  :    ,   '); removeLoadingIndicator(); }); 

Benutzerdefinierte Implementierungen



In anderen Sprachen


Ähnliche Funktionen gibt es in anderen Sprachen unter anderen Namen. Da es keinen universellen Mechanismus gibt, der sofort mit vielen Sprachen kompatibel ist, folgt dieses Dokument dem Beispiel der Namen aus den oben aufgeführten Bibliotheken. So sieht es in anderen Sprachen aus:


  • Rust - futures::join ;
  • C # - Task.WhenAll . Sie können entweder try / catch oder TaskContinuationOptions.OnlyOnFaulted .
  • Python - asyncio.wait mit der Option ALL_COMPLETED
  • Java - CompletableFuture.allOf

Materialien für weitere Studien



Protokoll der Sitzungen von TC39



Spezifikation



Implementierungen


Source: https://habr.com/ru/post/de459970/


All Articles