Die Operatoren async
/ await
erleichtern die Implementierung vieler asynchroner Versprechen. Sie ermöglichen es Ingenieuren auch, klareren, prägnanteren und testbaren Code zu schreiben.
Um dieses Thema zu verstehen, sollten Sie ein solides Verständnis dafür haben, wie Versprechen funktionieren.
Grundlegende Syntax
function slowlyResolvedPromiseFunc(string) { return new Promise(resolve => { setTimeout(() => { resolve(string); }, 5000); }); } async function doIt() { const myPromise = await slowlyResolvedPromiseFunc("foo"); console.log(myPromise); // "foo" } doIt();
Es gibt ein paar Dinge zu beachten:
- Die Funktion, die die
await
Deklaration umfasst, muss denasync
Operator enthalten. Dadurch wird dem JS-Interpreter mitgeteilt, dass er warten muss, bis das Versprechen aufgelöst oder abgelehnt wird. - Der
await
Operator muss während der const-Deklaration inline sein. - Dies funktioniert
reject
genauso gut wieresolve
.
Verschachtelte Promises vs. Async
/Await
Das Implementieren eines einzelnen Versprechens ist ziemlich einfach. Im Gegensatz dazu können verkettete Versprechen oder die Erstellung eines Abhängigkeitsmusters „Spaghetti-Code“ erzeugen.
In den folgenden Beispielen wird davon ausgegangen, dass die request-promise
Bibliothek als verfügbar ist rp
.
Verkettete / verschachtelte Versprechen
// First Promise const fooPromise = rp("//domain.com/foo"); fooPromise.then(resultFoo => { // Must wait for "foo" to resolve console.log(resultFoo); const barPromise = rp("//domain.com/bar"); const bazPromise = rp("//domain.com/baz"); return Promise.all([barPromise, bazPromise]); }).then(resultArr => { // Handle "bar" and "baz" resolutions here console.log(resultArr[0]); console.log(resultArr[1]); });
async
und await
Versprechen
// Wrap everything in an async function async function doItAll() { // Grab data from "foo" endpoint, but wait for resolution console.log(await rp("//domain.com/foo")); // Concurrently kick off the next two async calls, // don't wait for "bar" to kick off "baz" const barPromise = rp("//domain.com/bar"); const bazPromise = rp("//domain.com/baz"); // After both are concurrently kicked off, wait for both const barResponse = await barPromise; const bazResponse = await bazPromise; console.log(barResponse); console.log(bazResponse); } // Finally, invoke the async function doItAll().then(() => console.log('Done!'));
Die Vorteile der Verwendung async
und await
sollten klar sein. Dieser Code ist besser lesbar, modular und testbar.
Es ist fair zu bemerken, dass der zugrunde liegende Rechenprozess derselbe ist wie im vorherigen Beispiel, obwohl ein zusätzliches Gefühl der Parallelität besteht.
Umgang mit Fehlern / Ablehnung
Ein einfacher Try-Catch-Block verarbeitet ein abgelehntes Versprechen.
async function errorExample() { try { const rejectedPromise = await Promise.reject("Oh-oh!"); } catch (error) { console.log(error); // "Uh-oh!" } } errorExample();