Programmering

Asynkron JavaScript: Forklaringer om tilbakeringing og løfter

Det kan være vanskelig å håndtere asynkron kode, som betyr kode som ikke utføres umiddelbart som nettforespørsler eller tidtakere. JavaScript gir oss to måter ut av boksen for å håndtere asynkron atferd: tilbakeringing og løfter.

Tilbakekallinger var den eneste innfødte støttede måten å håndtere async-kode til 2016, da Love objektet ble introdusert til språket. Imidlertid hadde JavaScript-utviklere implementert lignende funksjonalitet på sine egne år før løfter kom på scenen. La oss se på noen av forskjellene mellom tilbakeringinger og løfter, og se hvordan vi håndterer koordinering av flere løfter.

Asynkrone funksjoner som bruker tilbakeringinger tar en funksjon som en parameter, som vil bli kalt når arbeidet er fullført. Hvis du har brukt noe sånt setTimeout i nettleseren har du brukt tilbakeringinger.

// Du kan definere tilbakeringingen din separat ...

la myCallback = () => {

console.log ('Called!');

};

setTimeout (myCallback, 3000);

// ... men det er også vanlig å se tilbakeringinger definert innebygd

setTimeout (() => {

console.log ('Called!');

}, 3000);

Vanligvis tar funksjonen som tar tilbakeringing det som sitt siste argument. Dette er ikke tilfelle ovenfor, så la oss late som det heter en ny funksjon vente det er akkurat som setTimeout men tar de to første argumentene i motsatt rekkefølge:

// Vi vil bruke den nye funksjonen vår slik:

waitCallback (3000, () => {

console.log ('Called!');

});

Nestede tilbakekallinger og undergangspyramiden

Tilbakekallinger fungerer bra for håndtering av asynkron kode, men de blir vanskelige når du begynner å måtte koordinere flere asynkrone funksjoner. For eksempel, hvis vi ønsket å vente i to sekunder og logge noe, så vente i tre sekunder og logge på noe annet, så vente i fire sekunder og logge på noe annet, blir syntaksen vår dypt nestet.

// Vi vil bruke den nye funksjonen vår slik:

waitCallback (2000, () => {

console.log ('First Callback!');

waitCallback (3000, () => {

console.log ('Second Callback!');

waitCallback (4000, () => {

console.log ('Tredje tilbakeringing!');

    });

  });

});

Dette kan virke som et trivielt eksempel (og det er det), men det er ikke uvanlig å komme med flere nettforespørsler på rad basert på returresultatene fra en tidligere forespørsel. Hvis AJAX-biblioteket ditt bruker tilbakeringinger, ser du strukturen ovenfor. I eksempler som er dypere nestede, vil du se det som blir referert til som undergangspyramiden, som får navnet sitt fra pyramideformen laget i det innrykkede hvite rommet i begynnelsen av linjene.

Som du kan se, blir koden vår strukturelt manglet og vanskeligere å lese når vi arbeider med asynkrone funksjoner som må skje sekvensielt. Men det blir enda vanskeligere. Tenk om vi ønsket å starte tre eller fire nettforespørsler og utføre noen oppgaver først etter at alle har kommet tilbake. Jeg oppfordrer deg til å prøve å gjøre det hvis du ikke har kjørt over utfordringen før.

Enklere asynkronisering med løfter

Løfter gir et mer fleksibelt API for å håndtere asynkrone oppgaver. Det krever at funksjonen skrives slik at den returnerer a Love objekt, som har noen standardfunksjoner for å håndtere påfølgende oppførsel og koordinere flere løfter. Hvis vår vent tilbakeringing funksjon var Love-basert, ville det bare ta ett argument, som er millisekundene å vente. Enhver påfølgende funksjonalitet vil være Lenket av løftet. Vårt første eksempel vil se slik ut:

la myHandler = () => {

console.log (‘Called!’);

};

waitPromise (3000). så (myHandler);

I eksemplet ovenfor, waitPromise (3000) returnerer a Love objekt som har noen metoder vi kan bruke, for eksempel deretter. Hvis vi ønsket å utføre flere asynkrone funksjoner etter hverandre, kunne vi unngå undergangspyramiden ved å bruke løfter. Denne koden, omskrevet for å støtte vårt nye løfte, vil se slik ut:

// Uansett hvor mange sekvensielle asynkroniseringsoppgaver vi har, lager vi aldri pyramiden.

waitPromise (2000)

.then (() => {

console.log ('First Callback!');

return waitPromise (3000);

  })

.then (() => {

console.log ('Second Callback!');

return waitPromise (4000);

  })

.then (() => {

console.log ('Second Callback!');

return waitPromise (4000);

  });

Enda bedre, hvis vi trenger å koordinere asynkrone oppgaver som støtter løfter, kan vi bruke dem alle, som er en statisk metode på Love objekt som tar flere løfter og kombinerer dem til ett. Det vil se ut som:

Promise.all ([

waitPromise (2000),

waitPromise (3000),

waitPromise (4000)

]). deretter (() => console.log ('Alt er gjort!'));

Neste uke skal vi se nærmere på hvordan løfter fungerer og hvordan vi kan bruke dem idiomatisk. Hvis du bare lærer JavaScript eller er interessert i å teste kunnskapen din, kan du prøve å vent tilbakeringing eller prøv å oppnå tilsvarende Lov. Alt med tilbakeringinger.

Ta alltid kontakt med meg på Twitter med kommentarer eller spørsmål.