Tilbake
5.5
Asynkron programmering og API-er

5.5 Asynkron programmering og API-er

Forstå asynkron programmering med Promises og async/await, og hent data med fetch().

70 min
8 oppgaver
Asynkron programmeringAPIfetch()Promise
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 8 oppgaver

Asynkron programmering og API-ar

Hittil har JavaScript-koden vår køyrt synkront – instruksjon for instruksjon, frå topp til botn. Men mange oppgåver i moderne webutvikling tek tid: hente data frå ein tenar, laste bilete, vente på brukarinput. Viss JavaScript måtte vente på at kvar slik operasjon vart ferdig før han heldt fram, ville nettsida fryse og bli ubrukeleg.

Løysinga er asynkron programmering – ein modell der tidkrevjande operasjonar vert starta og køyrer i bakgrunnen, medan resten av programmet held fram. Når operasjonen er ferdig, vert programmet varsla og kan handsame resultatet.

I dette kapittelet lærer vi om Promises, async/await og den kanskje viktigaste praktiske ferdigheita i moderne JavaScript: å hente data frå API-ar (Application Programming Interfaces) med fetch().

Asynkron programmering
Asynkron programmering er ein programmeringsmodell der operasjonar kan starte og fullførast uavhengig av programflyten, utan å blokkere køyringa av annan kode. I JavaScript tyder dette at tidkrevjande operasjonar som nettverksførespurnader, fillesing og timarar startar i bakgrunnen, medan programmet held fram med å køyre. Når den asynkrone operasjonen er ferdig, vert programmet varsla gjennom ein callback-funksjon, eit Promise eller async/await.

Lat oss sjå skilnaden mellom synkron og asynkron kode:

Synkron kode (blokkerande)

console.log("Steg 1");
console.log("Steg 2");  // Venter til steg 1 er ferdig
console.log("Steg 3");  // Venter til steg 2 er ferdig
// Utskrift: Steg 1, Steg 2, Steg 3 (i rekkefølge)

Asynkron kode (ikke-blokkerende)

console.log("Steg 1");

setTimeout(() => {
  console.log("Steg 2 (etter 2 sekunder)");
}, 2000);

console.log("Steg 3");
// Utskrift: Steg 1, Steg 3, Steg 2 (etter 2 sek)

I det asynkrone dømet vert «Steg 3» køyrt før «Steg 2» fordi setTimeout er asynkron – han startar ein timar i bakgrunnen og lèt resten av koden køyre vidare. Når timaren går ut etter 2 sekund, vert callback-funksjonen køyrd.

setTimeout er det enklaste dømet på asynkron kode, men i praksis er det nettverksførespurnader (henting av data frå API-ar) som er den viktigaste bruken av asynkron programmering.

API (Application Programming Interface)

Eit API er eit grensesnitt som lèt program kommunisere med kvarandre etter bestemte reglar. Web-API-ar er tenester som leverer data over internett via HTTP-førespurnader. Når JavaScript hentar vêrdata, kartinformasjon eller nyheiter frå ei ekstern teneste, kommuniserer det med eit API. API-ar tek imot førespurnader og returnerer data, vanlegvis i JSON-format. Dei fleste moderne nettsider og appar brukar API-ar for å hente og sende data.

fetch() er den innebygde JavaScript-funksjonen for å sende HTTP-førespurnader. Han er asynkron og returnerer eit Promise:

fetch("https://api.eksempel.no/data")
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error("Feil:", error);
  });

Lat oss bryte ned kva som skjer:

1. fetch(url) sender ein HTTP GET-førespurnad til URL-en
2. .then(response => response.json()) tek svaret frå tenaren og konverterer det frå JSON-tekst til eit JavaScript-objekt
3. .then(data => { ... }) lèt deg bruke dei konverterte dataene
4. .catch(error => { ... }) fangar opp feil (f.eks. nettverksproblem)

Praktisk døme med eit ekte API

// Hent et tilfeldig vitseriat fra et åpent API
fetch("https://official-joke-api.appspot.com/random_joke")
  .then(response => response.json())
  .then(joke => {
    console.log(joke.setup);
    console.log(joke.punchline);
  })
  .catch(error => {
    console.error("Kunne ikke hente vits:", error);
  });

Denne koden sender ein førespurnad til eit API som returnerer tilfeldige vitsar i JSON-format, konverterer svaret til eit JavaScript-objekt, og skriv ut oppsett og poeng.

Promise

Eit Promise er eit JavaScript-objekt som representerer det framtidige resultatet av ein asynkron operasjon. Namnet «promise» (lovnad) kjem av at objektet gir ein lovnad om at det vil levere eit resultat seinare. Eit Promise kan ha tre tilstandar: pending (operasjonen er i gang), fulfilled (operasjonen lukkast og har eit resultat) eller rejected (operasjonen feila). Du handterer utfallet med .then() for suksess og .catch() for feil.

Promise-kjeder med .then() kan bli vanskelege å lese. Moderne JavaScript tilbyr async/await som gjer asynkron kode mykje enklare:

async function hentData() {
  try {
    const response = await fetch("https://api.eksempel.no/data");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Feil:", error);
  }
}

hentData();

Nøkkelord:
- async framfor funksjonen markerer han som asynkron
- await pausar funksjonen til Promiset er fullført (kan berre brukast inne i async-funksjonar)
- try/catch handterer feil på ein oversiktleg måte

Samanlikning: .then() vs. async/await

// Med .then() (eldre stil)
fetch("https://api.eksempel.no/brukere")
  .then(response => response.json())
  .then(brukere => {
    console.log(brukere);
  })
  .catch(error => {
    console.error(error);
  });

// Med async/await (moderne, anbefalt)
async function hentBrukere() {
  try {
    const response = await fetch("https://api.eksempel.no/brukere");
    const brukere = await response.json();
    console.log(brukere);
  } catch (error) {
    console.error(error);
  }
}

Begge gjer nøyaktig det same, men async/await-versjonen er lettare å lese fordi han ser ut som vanleg synkron kode.

Nettverksførespurnader kan feile av mange grunnar: inga internettforbinding, tenaren er nede, feil URL, API-nøkkel er ugyldig, osv. God feilhandtering er difor avgjerande.

Sjekke HTTP-statuskoden

fetch() kastar berre ein feil ved nettverksproblem – han reknar HTTP-feil som 404 og 500 som vellukka førespurnader. Du må sjekke statuskoden sjølv:

async function hentData(url) {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error("HTTP-feil: " + response.status);
    }

    const data = await response.json();
    return data;

  } catch (error) {
    console.error("Noe gikk galt:", error.message);
    return null;
  }
}

response.ok er true for statuskodar 200-299 og false for andre. Ved å kaste ein feil med throw new Error() sikrar vi at feil vert fanga av catch-blokka.

Vise feilmeldingar til brukaren

async function lastInnVarsel() {
  const statusDiv = document.querySelector("#status");
  statusDiv.textContent = "Laster data...";

  try {
    const response = await fetch("https://api.met.no/weatherapi");

    if (!response.ok) {
      throw new Error("Kunne ikke hente værdata.");
    }

    const data = await response.json();
    statusDiv.textContent = "";
    visVardata(data);

  } catch (error) {
    statusDiv.textContent = "Feil: " + error.message;
    statusDiv.style.color = "red";
  }
}

Hittil har vi berre henta data (GET). For å sende data til ein tenar brukar vi POST-førespurnader:

async function sendKommentar(tekst) {
  try {
    const response = await fetch("https://api.eksempel.no/kommentarer", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        innhold: tekst,
        tidspunkt: new Date().toISOString(),
      }),
    });

    if (!response.ok) {
      throw new Error("Kunne ikke sende kommentar.");
    }

    const resultat = await response.json();
    console.log("Kommentar lagret:", resultat);

  } catch (error) {
    console.error("Feil:", error.message);
  }
}

fetch() tek eit valfritt options-objekt som andre argument:
- method: HTTP-metoden (POST, PUT, DELETE osv.)
- headers: Metainformasjon, her spesifiserer vi at vi sender JSON
- body: Sjølve dataene, konvertert til JSON-streng med JSON.stringify()

✏️Komplett døme: Vise data frå eit API i DOM-en

Her er eit komplett døme som hentar brukardata frå eit ope API og viser det på nettsida:

HTML:

<h2>Brukeroversikt</h2>
<button id="lastInn">Last inn brukere</button>
<div id="status"></div>
<div id="brukerliste"></div>

JavaScript:

const knapp = document.querySelector("#lastInn");
const statusDiv = document.querySelector("#status");
const listeDiv = document.querySelector("#brukerliste");

knapp.addEventListener("click", async function () {
  statusDiv.textContent = "Laster...";
  listeDiv.innerHTML = "";

  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");

    if (!response.ok) {
      throw new Error("Serverfeil: " + response.status);
    }

    const brukere = await response.json();
    statusDiv.textContent = brukere.length + " brukere funnet:";

    brukere.forEach(bruker => {
      const kort = document.createElement("div");
      kort.classList.add("bruker-kort");
      kort.innerHTML = `
        <h3>${bruker.name}</h3>
        <p>E-post: ${bruker.email}</p>
        <p>By: ${bruker.address.city}</p>
      `;
      listeDiv.appendChild(kort);
    });

  } catch (error) {
    statusDiv.textContent = "Feil: " + error.message;
    statusDiv.style.color = "red";
  }
});

Dette dømet kombinerer alt vi har lært: hendingshandtering (klikk-lyttar), asynkron programmering (async/await med fetch), feilhandtering (try/catch), JSON-parsing og DOM-manipulering (createElement, innerHTML, appendChild).

📝Oppgave 5.5.1

Kva tyder det at JavaScript er asynkront?

📝Oppgave 5.5.2

Kva er eit API i websamanheng?

📝Oppgave 5.5.3

Kva vert skrive ut av denne koden?

console.log("A");
setTimeout(() => console.log("B"), 0);
console.log("C");

📝Oppgave 5.5.4

Kva gjer response.json() i ein fetch()-førespurnad?

📝Oppgave 5.5.5

Skriv ein asynkron funksjon hentLand(navn) som brukar fetch() og async/await til å hente informasjon om eit land frå API-et https://restcountries.com/v3.1/name/{navn}. Funksjonen skal skrive ut det offisielle namnet og folketalet til landet til konsollen. Inkluder feilhandtering med try/catch.

📝Oppgave 5.5.6

Lag ein komplett nettside-funksjon som hentar ei liste med brukarar frå https://jsonplaceholder.typicode.com/users og viser dei som kort i ein <div id="brukere">. Kvart kort skal vise namnet, e-posten og firmaet til brukaren. Vis ei "Laster..."-melding medan data vert henta, og ei feilmelding viss noko går gale. Bruk async/await, DOM-manipulering og feilhandtering.

📝Oppgave 5.5.7

Kvifor kastar ikkje fetch() ein feil for HTTP-statuskode 404 (Ikkje funne)?

📝Oppgave 5.5.8

Skriv ein async funksjon sendTilbakemelding(navn, melding) som sender ein POST-førespurnad med JSON-data til https://jsonplaceholder.typicode.com/posts. Dataene skal innehalde title (namnet), body (meldinga) og userId sett til 1. Funksjonen skal returnere det oppretta objektet frå tenaren, eller null ved feil. Inkluder rette headers og feilhandtering.

Oppsummering

I dette kapittelet har du lært:

- Asynkron programmering: operasjonar utan å blokkere koden.
- API: grensesnitt som lèt program kommunisere.
- fetch(): hentar data frå eksterne API-ar.
- Promise: representerer eit framtidig resultat.
- async/await: moderne, lesbar syntaks for asynkron kode.

Nøkkelomgrep


OmgrepForklaring
Asynkron programmeringOperasjonar som ikkje blokkerer koden
APIGrensesnitt for kommunikasjon mellom program
PromiseObjekt for framtidig resultat av asynkron operasjon

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.