Hva det er og hvordan du bruker det

Når du skriver JavaScript-applikasjoner, kan du ha støtt på asynkrone funksjoner, for eksempel hentefunksjonen i nettleseren eller readFile-funksjonen i Nodejs.

Du kan ha fått uventede resultater hvis du brukte en av disse funksjonene som du normalt ville gjort. Dette er fordi de er asynkrone funksjoner. Denne artikkelen guider hva det betyr og hvordan du bruker asynkrone funksjoner som en proff.

Introduksjon til synkronfunksjon

JavaScript er et enkelt-tråds språk som bare kan gjøre én ting om gangen. Dette betyr at dersom prosessoren møter en funksjon som tar lang tid, venter JavaScript til hele funksjonen er utført før den går videre til andre deler av programmet.

De fleste funksjoner utføres utelukkende av prosessoren. Dette betyr at under utførelsen av nevnte funksjoner, uavhengig av hvor lang tid det tar, vil prosessoren være helt opptatt. Disse kalles synkrone funksjoner. Et eksempel på synkronfunksjon er definert nedenfor:

function add(a, b) {
    for (let i = 0; i < 1000000; i ++) {
        // Do nothing
    }
    return a + b;
}

// Calling the function will take a long time
sum = add(10, 5);

// However, the processor cannot move to the 
console.log(sum);

Denne funksjonen utfører en stor sløyfe hvis utførelse tar lang tid før den returnerer summen av de to argumentene.

Etter å ha definert funksjonen kalte vi den og lagret resultatet i sumvariabelen. Deretter logget vi verdien av sumvariabelen. Selv om det tar litt tid å utføre add-funksjonen, kan ikke prosessoren fortsette å logge summen før utførelsen er fullført.

De aller fleste funksjonene du vil møte vil oppføre seg på forutsigbare måter som den ovenfor. Noen funksjoner er imidlertid asynkrone og oppfører seg ikke som vanlige funksjoner.

Introduksjon til asynkron funksjon

Asynkrone funksjoner gjør mesteparten av arbeidet sitt utenfor prosessoren. Dette betyr at selv om funksjonen kan ta en stund å fullføre utførelse, vil prosessoren være ledig og fri til å gjøre mer arbeid.

Her er et eksempel på en slik funksjon:

fetch('https://jsonplaceholder.typicode.com/users/1');

For å øke effektiviteten lar JavaScript prosessoren gå videre til andre oppgaver som krever CPU selv før den asynkrone funksjonen er fullført.

Siden prosessoren gikk videre før kjøringen av den asynkrone funksjonen var fullført, vil ikke resultatet være umiddelbart tilgjengelig. Det vil vente. Hvis prosessoren prøvde å kjøre andre deler av programmet som var avhengig av det ventende resultatet, ville vi få feil.

  Slik endrer du foreldrekontroll på PS4

Derfor bør prosessoren kun kjøre deler av programmet som ikke er avhengig av det ventende resultatet. For å gjøre dette bruker moderne JavaScript løfter.

Hva er et løfte i JavaScript?

I JavaScript er et løfte en midlertidig verdi som en asynkron funksjon returnerer. Løfter er ryggraden i moderne asynkron programmering i JavaScript.

Etter at et løfte er opprettet, skjer én av to ting. Den løser enten når den asynkrone funksjonens returverdi er produsert eller avviser i tilfelle feil. Dette er hendelser innenfor et løftes livssyklus. Derfor kan vi knytte hendelsesbehandlere til løftet om å bli kalt når det løser seg eller avviser.

All koden som krever den endelige verdien av en asynkron funksjon kan knyttes til løftets hendelsesbehandler når det løser seg. All koden som håndterer feilen ved et avvist løfte vil også bli knyttet til dens tilsvarende hendelsesbehandler.

Her er et eksempel hvor vi leser data fra en fil i Nodejs.

const fs = require('fs/promises');

fileReadPromise = fs.readFile('./hello.txt', 'utf-8');

fileReadPromise.then((data) => console.log(data));

fileReadPromise.catch((error) => console.log(error));

I den første linjen importerer vi fs/promises-modulen.

På den andre linjen kaller vi readFile-funksjonen, og sender inn navnet og kodingen for filen hvis innhold vi ønsker å lese. Denne funksjonen er asynkron; derfor gir det et løfte. Vi lagrer løftet i fileReadPromise-variabelen.

I tredje linje har vi lagt ved en hendelseslytter for når løftet løser seg. Vi gjorde dette ved å kalle den daværende metoden på løfteobjektet. Som et argument for vår oppfordring til den daværende metoden, ga vi funksjonen til å kjøre hvis og når løftet løser seg.

I fjerde linje festet vi en lytter for når løftet avvises. Dette gjøres ved å kalle catch-metoden og sende inn feilhendelsesbehandleren som et argument.

En alternativ tilnærming er å bruke asynkrone og avvente søkeord. Vi vil dekke denne tilnærmingen neste.

Async and Await Explained

Async og Await nøkkelord kan brukes til å skrive asynkront Javascript på en måte som ser bedre ut syntaktisk. I denne delen vil jeg forklare hvordan du bruker nøkkelordene og hvilken effekt de har på koden din.

Nøkkelordet await brukes til å pause utførelsen av en funksjon mens man venter på at en asynkron funksjon skal fullføres. Her er et eksempel:

const fs = require('fs/promises');

function readData() {
	const data = await fs.readFile('./hello.txt', 'utf-8');

    // This line will not be executed until the data becomes available
	console.log(data);
}

readData()

Vi brukte nøkkelordet await mens vi ringte til readFile. Dette instruerte prosessoren til å vente til filen er lest før neste linje (console.log) kan kjøres. Dette bidrar til å sikre at kode som avhenger av en asynkron funksjons resultat ikke vil bli utført før resultatet blir tilgjengelig.

  Hvordan bli en programvareutviklingsingeniør i test (SDET)

Hvis du prøvde å kjøre koden ovenfor, vil du få en feil. Dette er fordi await kun kan brukes i en asynkron funksjon. For å erklære en funksjon som asynkron, bruker du nøkkelordet async før funksjonserklæringen slik:

const fs = require('fs/promises');

async function readData() {
	const data = await fs.readFile('./hello.txt', 'utf-8');

    // This line will not be executed until the data becomes available
	console.log(data);
}

// Calling the function so it runs
readData()

// Code at this point will run while waiting for the readData function to complete
console.log('Waiting for the data to complete')

Når du kjører denne kodebiten, vil du se at JavaScript kjører den ytre console.log mens du venter på at dataene som leses fra tekstfilen blir tilgjengelige. Når den er tilgjengelig, kjøres console.log inne i readData.

Feilhåndtering under bruk av søkeordene for async and await utføres vanligvis ved hjelp av prøve/fange blokker. Det er også viktig å vite hvordan sløyfe med asynkron kode.

Async og await er tilgjengelig i moderne JavaScript. Tradisjonelt ble asynkron kode skrevet ved bruk av tilbakeringinger.

Introduksjon til tilbakeringinger

En tilbakeringing er en funksjon som kalles opp når resultatet er tilgjengelig. All kode som krever returverdien vil bli lagt inn i tilbakeringingen. Alt annet utenfor tilbakeringingen avhenger ikke av resultatet og er derfor gratis å utføre.

Her er et eksempel som leser en fil i Nodejs.

const fs = require("fs");

fs.readFile("./hello.txt", "utf-8", (err, data) => {

	// In this callback, we put all code that requires 
	if (err) console.log(err);
	else console.log(data);
});

// In this part here we can perform all the tasks that do not require the result
console.log("Hello from the program")

I den første linjen importerte vi fs-modulen. Deretter kalte vi readFile-funksjonen til fs-modulen. ReadFile-funksjonen vil lese tekst fra en fil vi spesifiserer. Det første argumentet er hvilken fil det er, og det andre spesifiserer filformatet.

ReadFile-funksjonen leser teksten fra filer asynkront. For å gjøre dette tar den inn en funksjon som et argument. Dette funksjonsargumentet er en tilbakeringingsfunksjon og vil bli kalt når dataene er lest.

Det første argumentet som sendes når tilbakeringingsfunksjonen kalles, er en feil som vil ha en verdi hvis det oppstår en feil mens funksjonen kjører. Hvis det ikke oppstår noen feil, vil den være udefinert.

Det andre argumentet som sendes til tilbakeringingen er dataene som er lest fra filen. Koden inne i denne funksjonen vil få tilgang til dataene fra filen. Kode utenfor denne funksjonen krever ikke data fra filen; kan derfor kjøres mens du venter på data fra filen.

  Fiks Netflix Denne tittelen er ikke tilgjengelig for å se umiddelbart feil

Å kjøre koden ovenfor vil gi følgende resultat:

Viktige JavaScript-funksjoner

Det er noen nøkkelfunksjoner og egenskaper som påvirker hvordan asynkron JavaScript fungerer. De er godt forklart i videoen nedenfor:

Jeg har kort skissert de to viktige funksjonene nedenfor.

#1. Enkeltrådet

I motsetning til andre språk som lar programmereren bruke flere tråder, lar JavaScript deg bare bruke én tråd. En tråd er en sekvens av instruksjoner som logisk avhenger av hverandre. Flere tråder lar programmet kjøre en annen tråd når det oppstår blokkeringsoperasjoner.

Imidlertid legger flere tråder til kompleksitet og gjør det vanskeligere å forstå programmene som bruker dem. Dette gjør det mer sannsynlig at feil vil bli introdusert i koden, og det ville være vanskelig å feilsøke koden. JavaScript ble laget entrådet for enkelhets skyld. Som et enkelt-tråds språk er det avhengig av å være hendelsesdrevet for å håndtere blokkeringsoperasjoner effektivt.

#2. Hendelsesdrevet

JavaScript er også hendelsesdrevet. Dette betyr at noen hendelser skjer i løpet av et JavaScript-programs livssyklus. Som programmerer kan du knytte funksjoner til disse hendelsene, og hver gang hendelsen skjer, vil den vedlagte funksjonen bli kalt og utført.

Noen hendelser kan skyldes at resultatet av en blokkeringsoperasjon er tilgjengelig. I dette tilfellet kalles den tilhørende funksjonen opp med resultatet.

Ting du bør vurdere når du skriver asynkron JavaScript

I denne siste delen vil jeg nevne noen ting du bør vurdere når du skriver asynkron JavaScript. Dette vil inkludere nettleserstøtte, beste praksis og viktighet.

Nettleserstøtte

Dette er en tabell som viser støtten til løfter i forskjellige nettlesere.

Kilde: caniuse.com

Dette er en tabell som viser støtte for asynkrone nøkkelord i forskjellige nettlesere.

Kilde: caniuse.com

Beste praksis

  • Velg alltid asynkron/avvent, da det hjelper deg med å skrive renere kode som er lett å tenke på.
  • Håndter feil i try/catch-blokker.
  • Bruk nøkkelordet async bare når det er nødvendig å vente på resultatet av en funksjon.

Viktigheten av asynkron kode

Asynkron kode lar deg skrive mer effektive programmer som bare bruker én tråd. Dette er viktig ettersom JavaScript brukes til å bygge nettsteder som gjør mange asynkrone operasjoner, for eksempel nettverksforespørsler og lesing eller skriving av filer til disk. Denne effektiviteten har gjort det mulig for kjøretider som NodeJS å vokse i popularitet som den foretrukne kjøretiden for applikasjonsservere.

Siste ord

Dette har vært en lang artikkel, men i den kunne vi dekke hvordan asynkrone funksjoner skiller seg fra vanlige synkrone funksjoner. Vi dekket også hvordan du bruker asynkron kode ved å bruke bare løfter, asynkron/avvent nøkkelord og tilbakeringinger.

I tillegg dekket vi nøkkelfunksjoner i JavaScript. I den siste delen avsluttet vi med å dekke nettleserstøtte og beste praksis.

Deretter kan du sjekke ut Node.js» vanlige intervjuspørsmål.