JavaScript callbacks, beloften en async-functies deel 2

Invoering

In deel een van deze tutorial leerden we de principes achter asynchroon programmeren en het gebruik van callbacks. Om te evalueren, asynchrone programmering stelt ons in staat om code te schrijven die niet-blokkerend is door later blokkeertaken uit te voeren. Callback-functies bieden een manier om de uitvoering van onze code te synchroniseren. 

Het herhaaldelijk nesten van callbacks is echter geen goed patroon om te volgen. Hier komen beloftes te redden. Beloften zijn al een tijdje in JavaScript-bibliotheken gebruikt, maar nu kunt u ze native in uw code gebruiken. Async-functies verbeteren de beloftes door ons toe te staan ​​onze taken een voor een te schrijven zonder ons zorgen te maken over de timing van hun uitvoering.

Inhoud

  • Promises
  • Async-functies
  • Beoordeling
  • Middelen

Promises

Laten we eens kijken naar wat een belofte conceptueel is. Stel je het scenario voor waarin je online winkelt en een paar schoenen koopt. Wanneer u uitcheckt, ontvangt u een e-mail met een samenvatting van uw aankoop. 

Deze orderbevestiging is als een belofte. De belofte is uw garantie dat u later iets terug krijgt van het bedrijf. Terwijl je bestelling in behandeling is, stopt je leven natuurlijk niet. U blijft andere taken uitvoeren, zoals surfen op internet. Als uw bestelling is voltooid, ontvangt u een e-mail met de verzendinformatie. Het is mogelijk dat uw bestelling wordt afgewezen. Het door u bestelde artikel is mogelijk niet op voorraad of er is een probleem met uw betaalmethode. In dit geval krijgt u een e-mail met de foutmelding.

In code spreken is een belofte een object dat ervoor zorgt dat we een toekomstige waarde voor ons verzoek krijgen, ongeacht of het lukt of mislukt. Dit is de algemene vorm voor het maken en gebruiken van een belofte:

function task1 () return new Promise (functie (resolve, reject) resolve (data); reject (error););  task1 () .then (function (result) console.log (result);) .catch (function (error) console.log (error););

Als u een belofte wilt maken, maakt u een belofte-object en schrijft u uw asynchrone code in de callback-functie van de belofte. De gegevens die u wilt teruggeven van de belofte wordt doorgegeven als een argument voor de oplossen functie, en uw foutmelding wordt doorgegeven aan de afwijzen functie. We ketenen beloften aan elkaar met behulp van de dan methode. Hiermee kunnen we de taken sequentieel uitvoeren. 

Als we de resultaten van een taak moeten doorgeven aan de volgende taak, retourneren we deze in de dan methode. Misschien willen we beloftes samenvoegen als we geïnteresseerd zijn in het transformeren van waarden of moeten we onze code in een bepaalde volgorde uitvoeren. Aan het einde van de keten vangen we onze fouten op. Als er een fout optreedt in een van onze taken, worden de resterende taken overgeslagen en wordt de fout verzonden naar ons blok catch.

In deel een van deze zelfstudie hebben we callbacks gebruikt om een ​​bestand te openen en een bericht en de bijbehorende opmerkingen op te halen. Dit is hoe de complete code eruit ziet met behulp van beloftes:

index.js

const fs = require ('fs'); const path = require ('path'); const postsUrl = path.join (__ dirname, 'db / posts.json'); const commentsUrl = path.join (__ dirname, 'db / comments.json'); // stuur de gegevens terug vanuit onze bestandsfunctie loadCollection (url) return new Promise (function (resolve, reject) fs.readFile (url, 'utf8', function (error, data) if (error) reject (' error '); else resolve (JSON.parse (data));););  // een object retourneren op id-functie getRecord (collection, id) return new Promise (function (resolve, reject) const data = collection.find (function (element) return element.id == id;); op te lossen (data););  // retourneer een reeks opmerkingen voor een postfunctie getCommentsByPost (comments, postId) return comments.filter (function (comment) return comment.postId == postId;);  // initialisatiecode loadCollection (postsUrl) .then (functie (posts) return getRecord (posts, "001");) .then (function (post) console.log (post); return loadCollection (commentsUrl); ) .then (functie (opmerkingen) const postComments = getCommentsByPost (comments, "001"); console.log (postComments);) .catch (function (error) console.log (error););

Het verschil hier is dat onze methode om het bestand te openen nu is ingepakt in een belofte-object. En in plaats van onze taken te combineren met callbacks, worden ze aan elkaar geketend dan

Zoals u kunt zien, hebben we de noodzaak van callbacks niet geëlimineerd. We gebruiken ze alleen anders. Voordien hebben we onze callbacks genest, zodat we de uitvoering van onze code in de volgende taak konden voortzetten. 

Dit doet me denken aan wanneer ik klantenservice bel een probleem en in plaats van dat de agent mijn probleem oplost, word ik overgeplaatst naar iemand anders. Dat iemand anders de oproep misschien wel of niet oplost, maar voor de eerste agent is het de verantwoordelijkheid van iemand anders. 

Met beloften krijgen we iets terug voordat we naar de volgende taak gaan. Als we dat moeten meenemen naar de volgende voortzetting van onze code, kunnen we een dan uitspraak.

Taak

Gebruik beloftes en schrijf een programma dat een bestand met gebruikers opent, de gebruikersgegevens ophaalt en vervolgens een bestand met berichten opent en alle berichten van de gebruiker afdrukt.

Async-functies

Beloften zijn een verbetering van het ontwerp van ons programma, maar we kunnen het beter doen. Het zou erg handig zijn als we onze taken synchroon zouden kunnen uitvoeren als dit:

taak 1(); Task2 (); task3 ();

Nou, dat kunnen we met het async / await-patroon. Om dit te doen, beginnen we met het omwikkelen van onze taken in een async-functie. Deze functie geeft een belofte terug. Vervolgens implementeren we foutafhandeling door onze taken in een proberen te vangen uitspraak. 

Als de belofte is vervuld, zal het alle taken uitvoeren die binnenin ons zaten proberen blok. Als het wordt afgewezen, de vangst blok zal worden uitgevoerd. Het toevoegen van de wachten sleutelwoord voordat een taak ons ​​programma onderbreekt totdat de taak is voltooid. 

Dit is het algemene formulier voor het gebruik van asynchrone functies:

async-functie initTasks () try const a = wacht op task1 (); const b = wacht op task2 (); const c = wacht op taak3 (); // doe iets met a, b en c catch (error) // doe iets met het error-object initTasks ();

Met behulp van dit patroon kunnen we herschrijven hoe we onze code uitvoeren in ons bestandsvoorbeeld.

async-functie getPost () try const berichten = wacht op loadCollection (postsUrl); const post = wacht op getRecord (berichten, "001"); const comments = wacht op loadCollection (commentsUrl); const postComments = wacht op getCommentsByPost (opmerkingen, post.id); console.log (post); console.log (postComments);  catch (fout) console.log (fout);  getPost ();

Ik vind het leuk om onze async-code te structureren met een proberen te vangen omdat het de foutafhandelingscode duidelijk scheidt van de reguliere code. Als een van de code in onze proberen blok veroorzaakt een fout, deze wordt afgehandeld door de vangst blok. Plus, we kunnen een toevoegen Tenslotte blok dat code zal uitvoeren, ongeacht of onze taken slagen of falen. 

Een voorbeeld voor het gebruik van dit patroon is wanneer we opruimcode hebben die we moeten uitvoeren. Deze code hoeft niet noodzakelijkerwijs te zijn opgenomen in a Tenslotte blok. Het kan worden geschreven na de vangst verklaring, en het zal worden uitgevoerd. In beloftes is deze syntaxis niet ingebouwd. We zouden een andere moeten koppelen dan verklaring na onze vangst verklaring om hetzelfde effect te bereiken.

Taak

Gebruik async / await om een ​​programma te schrijven dat een bestand met gebruikers opent, de gebruikersinfo ophaalt en vervolgens een bestand met berichten opent en de info van de gebruiker en al zijn berichten afdrukt.

Beoordeling

Terugbellen is niet inherent slecht. Het doorgeven van functies naar andere functies is een handig patroon in JavaScript. Terugbellen wordt een probleem wanneer we ze gebruiken om de stroom van onze applicatielogica te beheersen. Aangezien JavaScript asynchroon is, moeten we ervoor zorgen hoe we onze code schrijven, omdat taken niet noodzakelijkerwijs eindigen in de volgorde waarin ze zijn geschreven. Dat is geen slechte zaak omdat we niet willen dat een taak de voortzetting van het programma blokkeert. 

Beloften zijn een beter patroon voor het schrijven van asynchrone code. Ze repareren niet alleen de rommel van geneste callbacks, maar houden ook de controle over het resultaat van een taak binnen de taak. Door controle over te dragen aan een andere taak, of die taak nu onze eigen code of een externe API is, is onze code minder betrouwbaar. Ten slotte stellen async-functies ons in staat onze code synchroon te schrijven, wat veel intuïtiever en gemakkelijker te begrijpen is.

Middelen

  • You Do not Know JS: Async & Performance Ch 3: Beloften
  • JavaScript-beloften: een inleiding
  • Async-functies: beloftes vriendelijk maken
  • Async / Await door Patrick Triest