Implementering af Async og afventer med generatorer

Foto af Blake Connally på Unsplash

I dag kan vi skrive vores asynkron kode på en synkron måde takket være async og afvente nøgleord. Dette gør det lettere at læse og forstå. For nylig undrede jeg mig imidlertid over, hvordan den samme effekt kunne opnås uden at bruge disse nøgleord.

Det viser sig at være ganske enkelt, da adfærd af async og afventer let kan emuleres ved hjælp af generatorer. Lad os kigge på det!

Gå videre, klon depotet, og lad os komme i gang.

generatorer

Jeg vil antage, at du har ringe eller ingen erfaring med generatorer, da de ærligt talt ikke er særlig nyttige, og at du nemt kan klare dig uden dem. Så rol ikke - vi starter med en hurtig påmindelse.

Generatorer er objekter oprettet af generatorfunktioner - funktioner med en * (stjerne) ved siden af ​​deres navn.

Disse generatorer har en forbløffende evne, der lader os stoppe udførelsen af ​​kode - når vi vil - ved at bruge nøgleordets udbytte.

Overvej dette eksempel:

const generator = (funktion * () {
  // venter på .næste ()
  const a = udbytte 5;
  // venter på .næste ()
  console.log (a); // => 15
}) ();

console.log (generator.next ()); // => {gjort: falsk, værdi: 5}
console.log (generator.next (15)); // => {gjort: sandt, værdi: udefineret}

I betragtning af at dette er absolutte grundlæggende, vil jeg anbefale, at inden du ruller videre, læser du denne artikel for at få et indblik i, hvad der virkelig sker her.

Hvis du har lyst til at have en stærk forståelse af de underliggende ideer, kan vi komme videre.

Hold fast, vent et øjeblik

Har du ikke nogensinde spekuleret på, hvordan afventer virkelig fungerer?

På en eller anden måde venter det bare på vores løfte om at returnere en værdi og fortsætte med henrettelsen. For mig ser det ud som noget, en generator ville være i stand til at gøre efter lidt finjustering.

Hvad vi kunne gøre, er bare at tage enhver afkastet værdi, sætte det i et løfte og derefter vente på, at løftet bliver løst. Bagefter returnerer vi det bare til generatoren ved at kalde generator.next (resolvedValue).

Lyder som en plan. Men først skal vi skrive nogle test bare for at være sikker på, at alt fungerer som forventet.

Hvad vores asynq-funktion skal gøre:

  • vent på asynkron kode, før du fortsætter udførelsen
  • returner et løfte med den returnerede værdi fra funktionen
  • prøv at prøve at fange arbejde på asynkron kode

Bemærk: fordi vi bruger generatorer, bliver vores afventning udbytte.

Okay, fantastisk! Nu kan vi tale om implementeringen.

Vores asynq-funktion tager som parameter en funktionsgenerator - ved at kalde den opretter vi en generator.

Bare for at være sikker, kalder vi isGeneratorLignende som kontrollerer, om den modtagne værdi er et objekt og har metoder næste gang og kast.

Derefter forbruger vi rekursivt hvert udbyttesøgeord ved at kalde generator.next (ensuredValue). Vi venter på, at det returnerede løfte er afgjort, og returnerer derefter dets resultat tilbage til generatoren ved at gentage hele processen.

Vi skal også tilslutte fangstbehandleren, så hvis funktionen kaster en undtagelse, kan vi fange den og returnere undtagelsen inde i funktionen ved at kalde generator.throw (fejl).

Nu håndteres eventuelle fejl ved fangst. Hvis der ikke var en prøve / fangst-blok på plads, ville en fejl simpelthen stoppe udførelsen helt - som enhver ubehandlet undtagelse - og vores funktion ville returnere et afvist løfte.

Når generatoren er færdig, returnerer vi generatorens returværdi i et løfte.

Efter at have kørt vores test kan vi nu se, at alt fungerer som forventet.

Afslutter

Selvom denne implementering sandsynligvis ikke er den, der bruges inden i JavaScript-motorerne, føles det bestemt godt at være i stand til at gøre sådan noget på vores egen.

Du er velkommen til at gå over koden igen. Jo bedre din forståelse af de underliggende ideer er, desto mere vil du være i stand til at sætte pris på glansen hos skaberne af async og vente på nøgleord.

Mange tak for læsningen! Jeg håber, du har fundet denne artikel informativ. Jeg håber også, at det hjalp dig med at se, at der ikke er nogen magi involveret i async og afventer nøgleord, og at de let kan udskiftes med generatorer.

Hvis du har spørgsmål eller kommentarer, er du velkommen til at placere dem i kommentarfeltet nedenfor eller sende mig en besked.

Tjek mine sociale medier!

Deltag i mit nyhedsbrev!

Oprindeligt offentliggjort på www.mcieslar.com den 6. august 2018.