De auteur heeft het COVID-19 Relief Fund geselecteerd om een donatie te ontvangen als onderdeel van het Write for DOnations-programma.
Introductie
In de begindagen van het internet bestonden websites vaak uit statische gegevens op een HTML-pagina. Maar nu webapplicaties interactiever en dynamischer zijn geworden, is het steeds noodzakelijker geworden om intensieve bewerkingen uit te voeren, zoals het maken van externe netwerkverzoeken om API-gegevens op te halen. Om deze bewerkingen in JavaScript te verwerken, moet een ontwikkelaar asynchrone programmeertechnieken gebruiken.
Aangezien JavaScript een single-threaded programmeertaal is met een synchroon uitvoeringsmodel dat de ene bewerking na de andere verwerkt, kan het slechts één verklaring tegelijk verwerken. Een handeling zoals het aanvragen van gegevens van een API kan echter een onbepaalde tijd in beslag nemen, afhankelijk van de grootte van de aangevraagde gegevens, de snelheid van de netwerkverbinding en andere factoren. Als API-aanroepen op een synchrone manier zouden worden uitgevoerd, zou de browser geen gebruikersinvoer kunnen verwerken, zoals scrollen of op een knop klikken, totdat die bewerking is voltooid. Dit staat bekend als blokkeren.
Om blokkerend gedrag te voorkomen, heeft de browseromgeving veel Web-API’s waar JavaScript toegang toe kan hebben die asynchroon zijn, wat betekent dat ze parallel kunnen worden uitgevoerd met andere bewerkingen in plaats van sequentieel. Dit is handig omdat het de gebruiker in staat stelt de browser normaal te blijven gebruiken terwijl de asynchrone bewerkingen worden verwerkt.
Als JavaScript-ontwikkelaar moet je weten hoe je kunt werken met asynchrone Web-API’s en hoe je de respons of fout van die bewerkingen kunt afhandelen. In dit artikel leer je over de gebeurtenislus, de oorspronkelijke manier om met asynchroon gedrag om te gaan via terugroepfuncties, de bijgewerkte ECMAScript 2015-toevoeging van beloftes, en de moderne praktijk van het gebruik van async/await
.
Opmerking: Dit artikel richt zich op client-side JavaScript in de browseromgeving. Dezelfde concepten zijn over het algemeen waar in de Node.js-omgeving, echter Node.js gebruikt zijn eigen C++ API’s in plaats van de Web-API’s van de browser. Voor meer informatie over asynchroon programmeren in Node.js, bekijk Hoe Asynchrone Code te Schrijven in Node.js.
De Gebeurtenislus
Deze sectie zal uitleggen hoe JavaScript asynchrone code behandelt met de event loop. Het zal eerst een demonstratie van de event loop in actie doorlopen en zal vervolgens de twee elementen van de event loop uitleggen: de stack en de queue.
JavaScript code die geen gebruik maakt van enige asynchrone Web API’s zal synchroon uitgevoerd worden – één voor één, sequentieel. Dit wordt gedemonstreerd door deze voorbeeldcode die drie functies oproept die elk een nummer naar de console afdrukken:
In deze code definieer je drie functies die getallen afdrukken met console.log()
.
Vervolgens roep je de functies aan:
De output zal gebaseerd zijn op de volgorde waarin de functies werden aangeroepen – first()
, second()
, dan third()
:
Output1
2
3
Wanneer een asynchrone Web API wordt gebruikt, worden de regels ingewikkelder. Een ingebouwde API waarmee je dit kunt testen is setTimeout
, die een timer instelt en een actie uitvoert na een bepaalde tijd. setTimeout
moet asynchroon zijn, anders zou de hele browser bevroren blijven tijdens het wachten, wat zou resulteren in een slechte gebruikerservaring.
Voeg setTimeout
toe aan de second
functie om een asynchrone aanvraag te simuleren:
setTimeout
neemt twee argumenten: de functie die het asynchroon zal uitvoeren en de hoeveelheid tijd die het zal wachten voordat het die functie aanroept. In deze code heb je console.log
ingepakt in een anonieme functie en die doorgegeven aan setTimeout
, vervolgens heb je de functie ingesteld om uit te voeren na 0
milliseconden.
Roep nu de functies aan, zoals je eerder hebt gedaan:
Je zou verwachten dat met een setTimeout
ingesteld op 0
het uitvoeren van deze drie functies nog steeds resulteert in de getallen die sequentieel worden afgedrukt. Maar omdat het asynchroon is, zal de functie met de time-out als laatste worden afgedrukt:
Output1
3
2
Het maakt niet uit of je de time-out op nul seconden of vijf minuten instelt – de console.log
die wordt aangeroepen door asynchrone code zal worden uitgevoerd na de synchrone top-level functies. Dit gebeurt omdat de JavaScript-hostomgeving, in dit geval de browser, een concept genaamd de gebeurtenislus gebruikt om gelijktijdige of parallelle gebeurtenissen af te handelen. Omdat JavaScript slechts één verklaring tegelijk kan uitvoeren, moet de gebeurtenislus worden geïnformeerd wanneer welke specifieke verklaring moet worden uitgevoerd. De gebeurtenislus behandelt dit met de concepten van een stack en een wachtrij.
Stack
De stack, of call stack, houdt de staat bij van welke functie momenteel wordt uitgevoerd. Als je niet bekend bent met het concept van een stack, kun je het je voorstellen als een array met “Last in, first out” (LIFO) eigenschappen, wat betekent dat je alleen items kunt toevoegen of verwijderen van het einde van de stack. JavaScript voert het huidige frame (of functieoproep in een specifieke omgeving) uit in de stack, verwijdert het vervolgens en gaat door naar de volgende.
Voor het voorbeeld met alleen synchrone code, behandelt de browser de uitvoering in de volgende volgorde:
- Voeg
first()
toe aan de stack, voerfirst()
uit, dat1
naar de console logt, verwijderfirst()
uit de stack. - Voeg
second()
toe aan de stack, voersecond()
uit, dat2
naar de console logt, verwijdersecond()
uit de stack. - Voeg
third()
toe aan de stack, voerthird()
uit, dat3
naar de console logt, verwijderthird()
uit de stack.
Het tweede voorbeeld met setTimeout
ziet er als volgt uit:
- Voeg
first()
toe aan de stack, voerfirst()
uit, dat1
naar de console logt, verwijderfirst()
uit de stack. - Voeg
second()
toe aan de stack, voersecond()
uit.- Voeg
setTimeout()
toe aan de stack, voer desetTimeout()
Web API uit, die een timer start en de anonieme functie toevoegt aan de wachtrij, verwijdersetTimeout()
uit de stack.
- Voeg
- Verwijder
second()
uit de stack. - Voeg
third()
toe aan de stack, voerthird()
uit die3
naar de console logt, verwijderthird()
uit de stack. - De event loop controleert de wachtrij op eventuele wachtende berichten en vindt de anonieme functie van
setTimeout()
, voegt de functie toe aan de stack die2
naar de console logt, en verwijdert deze vervolgens uit de stack.
Het gebruik van setTimeout
, een asynchrone Web API, introduceert het concept van de wachtrij, waar deze tutorial vervolgens op zal ingaan.
Wachtrij
De wachtrij, ook wel berichtenwachtrij of taakwachtrij genoemd, is een wachtgebied voor functies. Telkens wanneer de call stack leeg is, zal de event loop de wachtrij controleren op eventuele wachtende berichten, te beginnen bij het oudste bericht. Zodra het er een vindt, zal het deze toevoegen aan de stack, die de functie in het bericht zal uitvoeren.
In het setTimeout
voorbeeld wordt de anonieme functie direct uitgevoerd na de rest van de uitvoering op het hoogste niveau, omdat de timer is ingesteld op 0
seconden. Het is belangrijk om te onthouden dat de timer niet betekent dat de code exact na 0
seconden of na de opgegeven tijd zal worden uitgevoerd, maar dat het de anonieme functie na die tijd aan de wachtrij zal toevoegen. Dit wachtrij-systeem bestaat omdat als de timer de anonieme functie direct aan de stapel zou toevoegen wanneer de timer eindigt, dit de uitvoering van de huidige functie zou onderbreken, wat onbedoelde en onvoorspelbare effecten zou kunnen hebben.
Opmerking: Er is ook nog een andere wachtrij genaamd de taakwachtrij of microtaakwachtrij die beloften afhandelt. Microtaken zoals beloften worden met een hogere prioriteit afgehandeld dan macrotaken zoals setTimeout
.
Nu weet je hoe de gebeurtenis-lus de stapel en de wachtrij gebruikt om de uitvoervolgorde van code te beheren. De volgende taak is om uit te zoeken hoe je de uitvoervolgorde in je code kunt beheersen. Om dit te doen, zul je eerst leren over de originele manier om ervoor te zorgen dat asynchrone code correct wordt afgehandeld door de gebeurtenis-lus: callback-functies.
Callback-functies
In het setTimeout
-voorbeeld werd de functie met de time-out uitgevoerd na alles in de belangrijkste top-level uitvoeringscontext. Maar als je ervoor wilde zorgen dat een van de functies, zoals de derde
functie, na de time-out werd uitgevoerd, dan moest je asynchrone codeermethoden gebruiken. De time-out hier kan een asynchrone API-oproep voorstellen die gegevens bevat. Je wilt werken met de gegevens van de API-oproep, maar je moet ervoor zorgen dat de gegevens eerst worden geretourneerd.
De originele oplossing voor het omgaan met dit probleem is het gebruik van terugbel-functies. Terugbel-functies hebben geen speciale syntaxis; het zijn gewoon functies die als argument aan een andere functie zijn doorgegeven. De functie die een andere functie als argument aanneemt, wordt een hogere-orde functie genoemd. Volgens deze definitie kan elke functie een terugbel-functie worden als deze als argument wordt doorgegeven. Terugbellen zijn van nature niet asynchroon, maar kunnen worden gebruikt voor asynchrone doeleinden.
Hier is een syntactisch codevoorbeeld van een hogere-orde functie en een terugbel-functie:
In deze code definieer je een functie fn
, definieer je een functie hogereOrdeFunctie
die een functie terugbeling
als argument aanneemt, en geef je fn
door als een terugbeling aan hogereOrdeFunctie
.
Het uitvoeren van deze code zal het volgende opleveren:
OutputJust a function
Laten we teruggaan naar de eerste
, tweede
en derde
functies met setTimeout
. Dit is wat je tot nu toe hebt:
De taak is om de uitvoering van de derde
functie altijd te vertragen totdat de asynchrone actie in de tweede
functie is voltooid. Hier komen callbacks van pas. In plaats van de eerste
, tweede
en derde
op het topniveau van uitvoering uit te voeren, geef je de derde
functie door als een argument aan tweede
. De tweede
functie zal de callback uitvoeren nadat de asynchrone actie is voltooid.
Hier zijn de drie functies met een callback toegepast:
Voer nu eerste
en tweede
uit, en geef vervolgens derde
als argument door aan tweede
:
Na het uitvoeren van dit codeblok ontvang je de volgende uitvoer:
Output1
2
3
Eerst zal 1
worden afgedrukt, en nadat de timer is voltooid (in dit geval nul seconden, maar je kunt dit naar believen wijzigen) zal het 2
en vervolgens 3
afdrukken. Door een functie als een callback door te geven, heb je met succes de uitvoering van de functie vertraagd totdat de asynchrone Web API (setTimeout
) is voltooid.
Het belangrijkste punt hier is dat callbackfuncties niet asynchroon zijn—setTimeout
is de asynchrone Web API die verantwoordelijk is voor het afhandelen van asynchrone taken. De callbackfunctie geeft je alleen de mogelijkheid om te worden geïnformeerd wanneer een asynchrone taak is voltooid en behandelt het succes of falen van de taak.
Nu je hebt geleerd hoe je callbacks kunt gebruiken om asynchrone taken af te handelen, legt de volgende sectie de problemen uit van het te veel nesten van callbacks en het creëren van een “pyramide van ellende.”
Geneste Callbacks en de Pyramide van Ellende
Callbackfuncties zijn een effectieve manier om uitgestelde uitvoering van een functie te verzekeren totdat een andere is voltooid en terugkeert met gegevens. Echter, vanwege de geneste aard van callbacks, kan de code rommelig worden als je veel opeenvolgende asynchrone verzoeken hebt die van elkaar afhankelijk zijn. Dit was een grote frustratie voor JavaScript-ontwikkelaars in het begin, en als gevolg hiervan wordt code die geneste callbacks bevat vaak de “pyramide van ellende” of “callbackhel” genoemd.
Hier is een demonstratie van geneste callbacks:
In deze code is elke nieuwe setTimeout
genest binnen een hogere-ordefunctie, waardoor een piramidevorm van steeds dieper geneste callbacks ontstaat. Als je deze code uitvoert, krijg je het volgende:
Output1
2
3
In de praktijk kan dit veel ingewikkelder worden met echte asynchrone code. Waarschijnlijk moet je foutafhandeling doen in asynchrone code, en vervolgens wat gegevens doorgeven van elke respons naar het volgende verzoek. Als je dit met terugbellen doet, zal je code moeilijk te lezen en te onderhouden zijn.
Hier is een uitvoerbaar voorbeeld van een meer realistische “pyramide van ellende” waar je mee kunt experimenteren:
In deze code moet je elke functie laten omgaan met een mogelijke response
en een mogelijke error
, wat de functie callbackHell
visueel verwarrend maakt.
Het uitvoeren van deze code zal het volgende opleveren:
Output
First 9
Second 3
Error: Whoa! Something went wrong.
at asynchronousRequest (<anonymous>:4:21)
at second (<anonymous>:29:7)
at <anonymous>:9:13
Deze manier van omgaan met asynchrone code is moeilijk te volgen. Als gevolg hiervan werd het concept van promises geïntroduceerd in ES6. Dit is het onderwerp van het volgende gedeelte.
Beloftes
A promise represents the completion of an asynchronous function. It is an object that might return a value in the future. It accomplishes the same basic goal as a callback function, but with many additional features and a more readable syntax. As a JavaScript developer, you will likely spend more time consuming promises than creating them, as it is usually asynchronous Web APIs that return a promise for the developer to consume. This tutorial will show you how to do both.
Het maken van een belofte
Je kunt een belofte initialiseren met de syntax new Promise
, en je moet deze initialiseren met een functie. De functie die aan een belofte wordt doorgegeven, heeft de parameters resolve
en reject
. De functies resolve
en reject
behandelen respectievelijk het succes en het falen van een operatie.
Schrijf de volgende regel om een belofte te declareren:
Als je de geïnitialiseerde belofte in deze staat inspecteert met de console van je webbrowser, zul je zien dat deze de status pending
heeft en een waarde van undefined
:
Output__proto__: Promise
[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined
Tot nu toe is er niets ingesteld voor de belofte, dus deze zal daar voor altijd in een pending
-status blijven staan. Het eerste wat je kunt doen om een belofte uit te proberen, is de belofte vervullen door deze op te lossen met een waarde:
Nu, bij inspectie van de belofte, zul je merken dat deze de status fulfilled
heeft en een w aarde
ingesteld op de waarde die je aan resolve
hebt doorgegeven:
Output__proto__: Promise
[[PromiseStatus]]: "fulfilled"
[[PromiseValue]]: "We did it!"
Zoals aan het begin van dit gedeelte vermeld, is een belofte een object dat een waarde kan teruggeven. Na succesvol te zijn vervuld, wordt de w aarde
van undefined
naar gevulde gegevens gewijzigd.
A promise can have three possible states: pending, fulfilled, and rejected.
- In afwachting – Initieel staat vóór het worden opgelost of verworpen
- Vervuld – Succesvolle operatie, belofte is vervuld
- Afgewezen – Mislukte operatie, belofte is afgewezen
Na vervuld of afgewezen te zijn, is een belofte afgehandeld.
Nu je een idee hebt van hoe beloftes worden gemaakt, laten we eens kijken hoe een ontwikkelaar deze beloftes kan gebruiken.
Het verbruiken van een Belofte
De belofte in de laatste sectie is vervuld met een waarde, maar je wilt ook in staat zijn om toegang te krijgen tot de waarde. Beloftes hebben een methode genaamd then
die zal worden uitgevoerd nadat een belofte resolve
heeft bereikt in de code. then
zal de waarde van de belofte teruggeven als een parameter.
Dit is hoe je de w aarde
van de voorbeeldbelofte zou retourneren en loggen:
De belofte die je hebt gemaakt had een [[PromiseValue]]
van We hebben het gedaan!
. Deze waarde is wat in de anonieme functie zal worden doorgegeven als respons
:
OutputWe did it!
Tot nu toe was het voorbeeld dat je hebt gemaakt niet betrokken bij een asynchrone Web API – het legde alleen uit hoe je een native JavaScript-belofte kunt maken, oplossen en consumeren. Met behulp van setTimeout
kun je een asynchrone aanvraag testen.
De volgende code simuleert gegevens die worden geretourneerd vanuit een asynchrone aanvraag als een belofte:
Het gebruik van de then
-syntax zorgt ervoor dat de response
alleen gelogd wordt wanneer de setTimeout
-operatie is voltooid na 2000
milliseconden. Dit alles gebeurt zonder het nesten van callbacks.
Nu, na twee seconden, zal het de belofte waarde oplossen en zal het gelogd worden in then
:
OutputResolving an asynchronous request!
Beloftes kunnen ook geketend worden om gegevens door te geven aan meer dan één asynchrone operatie. Als er een waarde wordt geretourneerd in then
, kan er een andere then
worden toegevoegd die vervult zal worden met de geretourneerde waarde van de vorige then
:
De vervulde respons in de tweede then
zal de retourwaarde loggen:
OutputResolving an asynchronous request! And chaining!
Aangezien then
geketend kan worden, maakt het de consumptie van beloftes mogelijk om meer synchroon te lijken dan callbacks, aangezien ze niet genest hoeven te worden. Dit maakt het mogelijk om meer leesbare code te schrijven die gemakkelijker te onderhouden en te verifiëren is.
Foutafhandeling
Tot nu toe heb je alleen een belofte afgehandeld met een succesvolle resolve
, die de belofte in een vervulde
toestand plaatst. Maar vaak moet je ook een fout afhandelen bij een asynchrone aanvraag – als de API down is, of als er een verkeerde of ongeautoriseerde aanvraag wordt verzonden. Een belofte zou beide gevallen moeten kunnen afhandelen. In dit gedeelte maak je een functie om zowel het succes- als het foutgeval van het maken en verbruiken van een belofte uit te testen.
Deze getUsers
-functie zal een vlag doorgeven aan een belofte, en de belofte retourneren:
Stel de code zo op dat als onSuccess
true
is, de timeout vervuld zal worden met wat data. Als false
zal de functie worden afgewezen met een fout:
Voor het succesvolle resultaat retourneer je JavaScript-objecten die voorbeeldgegevens van gebruikers voorstellen.
Om de fout af te handelen, gebruik je de catch
-instantiemethode. Dit geeft je een foutafhandelingscallback met de error
als parameter.
Voer het getUser
-commando uit met onSuccess
ingesteld op false
, gebruikmakend van de then
-methode voor het succesgeval en de catch
-methode voor de fout:
Sinds de fout is veroorzaakt, zal de then
-clausule worden overgeslagen en zal de catch
de fout afhandelen:
OutputFailed to fetch data!
Als je de vlag omschakelt en in plaats daarvan resolve
gebruikt, zal de catch
worden genegeerd en zal de data worden geretourneerd:
Dit zal de gebruikersgegevens opleveren:
Output(3) [{…}, {…}, {…}]
0: {id: 1, name: "Jerry"}
1: {id: 2, name: "Elaine"}
3: {id: 3, name: "George"}
Ter referentie, hier is een tabel met de handler-methoden op Promise
-objecten:
Method | Description |
---|---|
then() |
Handles a resolve . Returns a promise, and calls onFulfilled function asynchronously |
catch() |
Handles a reject . Returns a promise, and calls onRejected function asynchronously |
finally() |
Called when a promise is settled. Returns a promise, and calls onFinally function asynchronously |
Beloften kunnen verwarrend zijn, zowel voor nieuwe ontwikkelaars als voor ervaren programmeurs die nog nooit in een asynchrone omgeving hebben gewerkt. Zoals echter vermeld, is het veel gebruikelijker om beloften te consumeren dan ze te maken. Meestal levert een browser’s Web API of een externe bibliotheek de belofte en hoef je deze alleen maar te consumeren.
In het laatste gedeelte over beloften zal deze tutorial een veelvoorkomend gebruiksscenario van een Web API die beloften retourneert aanhalen: de Fetch API.
Het gebruik van de Fetch API met Beloften
Een van de meest nuttige en vaak gebruikte Web API’s die een belofte retourneert, is de Fetch API, waarmee je een asynchrone resource-aanvraag over een netwerk kunt maken. fetch
is een tweedelig proces en vereist daarom het koppelen van then
. Dit voorbeeld demonstreert het gebruik van de GitHub API om gegevens van een gebruiker op te halen, terwijl ook eventuele potentiële fouten worden afgehandeld:
De fetch
-aanvraag wordt verzonden naar de URL https://api.github.com/users/octocat
, die asynchroon wacht op een antwoord. De eerste then
geeft het antwoord door aan een anonieme functie die het antwoord opmaakt als JSON-gegevens, en geeft vervolgens de JSON door aan een tweede then
die de gegevens naar de console logt. De catch
-verklaring logt eventuele fouten naar de console.
Het uitvoeren van deze code zal het volgende opleveren:
Outputlogin: "octocat",
id: 583231,
avatar_url: "https://avatars3.githubusercontent.com/u/583231?v=4"
blog: "https://github.blog"
company: "@github"
followers: 3203
...
Dit zijn de opgevraagde gegevens van https://api.github.com/users/octocat
, weergegeven in JSON-indeling.
Deze sectie van de tutorial liet zien dat beloftes veel verbeteringen bevatten voor het omgaan met asynchrone code. Maar, hoewel het gebruik van then
om asynchrone acties te behandelen gemakkelijker te volgen is dan de piramide van terugroepingen, geven sommige ontwikkelaars nog steeds de voorkeur aan een synchrone opmaak voor het schrijven van asynchrone code. Om aan deze behoefte tegemoet te komen, introduceerde ECMAScript 2016 (ES7) async
-functies en het await
-trefwoord om het werken met beloftes gemakkelijker te maken.
Async Functies met async/await
Een async
functie stelt je in staat om asynchrone code te behandelen op een manier die synchroon lijkt. async
functies gebruiken nog steeds promises onder de motorkap, maar hebben een meer traditionele JavaScript-syntax. In deze sectie ga je voorbeelden van deze syntax uitproberen.
Je kunt een async
functie maken door het async
trefwoord toe te voegen vóór een functie:
Hoewel deze functie nog niets asynchroon afhandelt, gedraagt het zich anders dan een traditionele functie. Als je de functie uitvoert, zul je merken dat het een promise retourneert met een [[PromiseStatus]]
en [[PromiseValue]]
in plaats van een retourwaarde.
Probeer dit uit door een oproep naar de getUser
functie te loggen:
Dit zal het volgende geven:
Output__proto__: Promise
[[PromiseStatus]]: "fulfilled"
[[PromiseValue]]: Object
Dit betekent dat je een async
functie kunt behandelen met then
op dezelfde manier als je een promise zou kunnen behandelen. Probeer dit uit met de volgende code:
Deze oproep naar getUser
geeft de retourwaarde door aan een anonieme functie die de waarde naar de console logt.
Je zult het volgende ontvangen wanneer je dit programma uitvoert:
Output{}
Een async
-functie kan een promise die binnenin wordt aangeroepen afhandelen met behulp van de await
-operator. await
kan worden gebruikt binnen een async
-functie en zal wachten totdat een promise is afgehandeld voordat de aangewezen code wordt uitgevoerd.
Met deze kennis kunt u de Fetch-aanvraag uit het vorige gedeelte herschrijven met async
/await
als volgt:
De await
-operators zorgen ervoor dat de data
niet wordt gelogd voordat het verzoek deze met gegevens heeft gevuld.
Nu kan de uiteindelijke data
worden afgehandeld binnen de getUser
-functie, zonder dat er gebruik hoeft te worden gemaakt van then
. Dit is de uitvoer van het loggen van data
:
Outputlogin: "octocat",
id: 583231,
avatar_url: "https://avatars3.githubusercontent.com/u/583231?v=4"
blog: "https://github.blog"
company: "@github"
followers: 3203
...
Let op: In veel omgevingen is async
nodig om await
te gebruiken — echter, sommige nieuwe versies van browsers en Node staan top-level await
toe, waardoor je de noodzaak om een async-functie te maken om de await
in te wikkelen, kunt omzeilen.
Tenslotte, aangezien u de vervulde promise binnen de asynchrone functie afhandelt, kunt u ook de fout afhandelen binnen de functie. In plaats van de catch
-methode te gebruiken met then
, zult u het try
/catch
-patroon gebruiken om de uitzondering af te handelen.
Voeg de volgende gemarkeerde code toe:
Het programma zal nu naar het catch
-blok springen als het een fout ontvangt en die fout naar de console loggen.
Moderne asynchrone JavaScript-code wordt meestal behandeld met de syntaxis async
/await
, maar het is belangrijk om een werkende kennis te hebben van hoe promises werken, vooral omdat promises in staat zijn tot extra functies die niet kunnen worden afgehandeld met async
/await
, zoals het combineren van promises met Promise.all()
.
Opmerking: async
/await
kan worden gereproduceerd door generators in combinatie met promises te gebruiken om meer flexibiliteit aan uw code toe te voegen. Om meer te leren, bekijk onze zelfstudie Begrip Generators in JavaScript.
Conclusie
Omdat Web API’s vaak gegevens asynchroon leveren, is het leren omgaan met het resultaat van asynchrone acties een essentieel onderdeel van het zijn van een JavaScript-ontwikkelaar. In dit artikel heb je geleerd hoe de hostomgeving de gebeurtenislus gebruikt om de uitvoeringsvolgorde van code te behandelen met de stack en queue. Je hebt ook voorbeelden geprobeerd van drie manieren om het succes of falen van een asynchrone gebeurtenis af te handelen, met terugroepingen, beloftes en async
/await
-syntax. Ten slotte heb je de Fetch Web API gebruikt om asynchrone acties af te handelen.
Voor meer informatie over hoe de browser parallelle gebeurtenissen afhandelt, lees Concurrentiemodel en de gebeurtenislus op het Mozilla Developer Network. Als je meer wilt leren over JavaScript, keer dan terug naar onze Hoe te coderen in JavaScript serie.