# Async/Await

Met de release van ES7 in 2017 is er een handige syntax toegevoegd aan JavaScript: de async/await. Dit is een syntax waarmee asynchrone code in een meer synchrone stijl geschreven kan worden. Dit heeft een grote impact op de syntactische kwaliteit van de code en dus ook in hoeverre de code goed te onderhouden is.

Er is met andere woorden inhoudelijk niets veranderd, het is gewoon een aangenamere syntax om asynchrone functies uit te voeren.

# Syntax

Om deze techniek te gebruiken moet je de functie prependen of voorafgaan met het woordje async. Zonder deze prefix zal je niet gebruik kunnen maken van await.

# Async

Het async-woord vóór een functiedeclaratie, duidt aan dat de functie asynchrone code bevat. Het is verplicht te gebruiken wanneer je await zal willen toepassen.

async function fetchData() {
  // Asynchrone operatie
  return "Gegevens opgehaald";
}
1
2
3
4
async function fetchData() {
  // In dit voorbeeld is async niet verplicht.
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log("Data is opgehaald");
      resolve();
    }, 2000);
  });
}
1
2
3
4
5
6
7
8
9

# Await

Het await-woord wordt gebruikt binnen een async-functie om te wachten tot een Promise is vervuld, en dan het resultaat terug te geven. Om iets te kunnen awaiten moet deze een Promise of Error terug geven.

Later leren we over de fetch-functie, deze zal ook een Promise of Error teruggeven achter de schermen en kunnen we awaiten.

async function processData() {
  const result = await fetchData();
  console.log("Verwerkte gegevens:", result);
}
1
2
3
4
const getData = async () => {
  const response = await fetch("//jsonplaceholder.typicode.com/todos/1");
  const data = await response.json();
  console.log(data);
  return data;
};

getData();
1
2
3
4
5
6
7
8

# Combinatie

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Deze data komt van de server.");
    }, 2000);
  });
}

async function processData() {
  const data = await fetchData();
  console.log("Hier hebben we op moeten wachten:", data);
  return data;
}

processData();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Foutafhandeling

Fouten binnen een async-functie kunnen worden afgehandeld met een try/catch-blok, vergelijkbaar met synchrone code.

async function fetchData() {
  throw new Error("Er is een fout opgetreden");
}

async function processData() {
  try {
    await fetchData();
  } catch (error) {
    console.error("Fout tijdens de verwerking:", error.message);
  }
}
1
2
3
4
5
6
7
8
9
10
11
const getData = async (dataType) => {
  try {
    const response = await fetch(
      `//jsonplaceholder.typicode.com/${dataType}/1`
    );
    const data = await response.json();
    return data;
  } catch (err) {
    console.log(err);
  }
};

const todos = getData("todos");
console.log("Todos van een externe API", todos);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function fetchData() {
  const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
  const data = await response.json();
  return data;
}

async function processData() {
  try {
    const result = await fetchData();
    console.log("Verwerkte gegevens:", result);
  } catch (error) {
    console.error("Fout bij ophalen van gegevens:", error);
  }
}

processData();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Finally

Het finally-blok in een try...catch...finally-structuur wordt altijd uitgevoerd, ongeacht of er een fout optreedt of niet. Dit is handig voor situaties waarin bepaalde opruimacties noodzakelijk zijn, zoals het sluiten van bestanden of netwerkverbindingen, ongeacht het succes van eerdere operaties.

Laten we dit begrijpen aan de hand van een eenvoudig voorbeeld. Stel je voor dat we een functie hebben, askDadForSmartphone(true), die kan resulteren in een fout, maar we willen altijd de boodschap "Do something for all :)"weergeven, ongeacht of er een fout optreedt of niet.


try {
  // Probeer iets te doen dat een fout kan veroorzaken
  askDadForSmartphone(true);
} catch (error) {
  // Behandel de fout als deze zich voordoet
} finally {
  // Voer deze code altijd uit, ongeacht of er een fout is opgetreden of niet
  console.info("Do something for all :)");
}
1
2
3
4
5
6
7
8
9
10

In dit voorbeeld wordt console.info("Do something for all :)"); altijd uitgevoerd, ongeacht of askDadForSmartphone(true); een fout veroorzaakt of niet. Dit mechanisme waarborgt dat bepaalde acties altijd plaatsvinden, ongeacht het resultaat van de voorgaande code.

Belangrijk om te onthouden is dat als er een fout optreedt in het finally-blok, deze de oorspronkelijke fout zal overschrijven. Het is daarom raadzaam om te voorkomen dat er fouten worden gegenereerd binnen het finally-blok, om onnodige complicaties te vermijden.

Refactor

(async () => {
  const willIGetNewSmartphone = (isDadHappy) => {
    return new Promise((resolve, reject) => {
      if (isDadHappy) {
        resolve({
          brand: "Xiaomi",
          color: "Gradient Blue to Green",
        });
      } else {
        reject(new Error("Dad is not happy"));
      }
    });
  };

  const showOff = (phone) => {
    return new Promise((resolve, reject) => {
      const message = `Hey friend, I have a new ${phone.color} ${phone.brand} phone.`;
      resolve(message);
    });
  };

  const askDadForSmartphone = async (isDadHappy) => {
    try {
      const phone = await willIGetNewSmartphone(isDadHappy);
      const message = await showOff(phone);

      console.log(message);
    } catch (error) {
      console.error(error);
    } finally {
      console.info("Do something for all :)");
    }
  };

  await askDadForSmartphone(true);
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
© 2025 Arteveldehogeschool Laatst bijgewerkt: 13/1/2025, 10:02:14