# Foutafhandelingen

Foutafhandelingen (Eng. exception handling) zullen ons leren omgaan met foutmeldingen in JavaScript. Het afhandelen van fouten gebeurt in twee stappen:

  • Het werpen van fouten (throw)
  • Het opvangen van fouten (try catch finally)

# Het werpen van fouten

# throw statement

Het throw statement wordt gebruikt om een fout te werpen (Eng. throw an exception). Het throw statement wordt gevolgd door een expressie.

Het type van de expressie is niet van een specifiek type, dit kan een string, numerieke waarde, boolean … zijn, bijv.:

throw "Error2"; // String type
throw 42; // Number type
throw true; // Boolean type
throw {
  toString: function () {
    return "I'm an object!";
  },
};
1
2
3
4
5
6
7
8

Bij voorkeur werpen we een fout op dat een instantie is van het ingebouwde/globale Error object (of een afgeleide ervan via overerving). Dit object bevat meer informatie over de fout, je krijgt de name en message. De name is éen van de constructors zoals: ‘Error’, ‘ReferenceError’, ‘SyntaxError’, …

throw new Error("Can't fetch the data from the server!");
1

Opmerking

Een instantie van Error aanvaardt enkel strings, als je een object meegeeft zal dit worden omgezet in [Object obj]

# try…catch…finally statement

Het try…catch statement bevat een try blok dat één of meerdere acties of statements bevat, en het catch blok bevat één of meerdere acties of statements die uitgevoerd zullen worden indien een fout wordt geworpen in de try blok.

try {
  // Code die mogelijk een fout veroorzaakt
  let result = x + y; // Stel x en y zijn niet gedefinieerd
  console.log(result); // Deze regel wordt niet bereikt als er een fout optreedt
} catch (error) {
  // Code om de fout af te handelen
  console.error("Er is een fout opgetreden:", error.message);
} finally {
  // Code die altijd wordt uitgevoerd, ongeacht of er een fout is opgetreden
  console.log("De try-catch-block is voltooid.");
}
1
2
3
4
5
6
7
8
9
10
11

Indien er geen fout wordt geworpen in het try statement dan zullen de instructies op een normale manier afgehandeld worden. Het catch statement wordt dan overgeslagen.

try {
  // Code that may throw an error
  throw new Error("This is a custom error message");
} catch (error) {
  // Code to handle the error
  console.error("An error occurred:", error.message);
}
1
2
3
4
5
6
7

Het volgende voorbeeld gebruikt een try…catch statement waarin we de naam van de maand wil opvragen op basis van een positief geheel getal, namelijk de nummer van de maand, bijv.: 1 komt overeen met Jan, 12 komt overeen met Dec … De functie getMonthNameByNumber voert deze functionaliteit uit met als argument de opgegeven numerieke waarde van een maand. Is dit cijfer niet aanwezig, dan wordt een fout geworden met als expressie de string "INVALID_MONTH_NUMBER".

function getMonthNameByNumber(monthNumber) {
  monthNumber = monthNumber - 1;
  const months = [
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
  ];
  if (months[monthNumber]) {
    return months[monthNumber];
  } else {
    throw new Error("INVALID_MONTH_NUMBER");
  }
}

let monthName,
  monthNumber = 12;
try {
  monthName = getMonthNameByNumber(monthNumber);
  console.log(monthName);
} catch (e) {
  monthName = "unknown";
  console.error(monthName);
}
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

Kennen we de waarde 13 toe aan de variabele monthNumber, dan zal een fout geworpen worden, waardoor het catch statement wordt uitgevoerd. Het argument e (kan ook een andere naam zijn) bevat informatie over de fout die is opgetreden.

Het try…catch statement kan herschreven worden door gebruik te maken van de parameter e.

let monthNumber = 13;
try {
  const monthName = getMonthNameByNumber(monthNumber);
  console.log(monthName);
} catch (e) {
  console.error(e, e.message);
}
1
2
3
4
5
6
7

Het finally blok bevat statements die uitgevoerd zullen worden nadat een try en catch statement afgehandeld zijn. Pas daarna zullen de instructies na het try…catch…finally statement uitgevoerd worden. Het finally statement wordt altijd uitgevoerd ongeacht of er al dan niet een fout is opgetreden. Binnen het finally statement kunnen we ervoor zorgen dat bepaalde resources op een nette manier terug worden vrijgegeven.

# Fouttypes

De fouttypes (Eng. exception types) kunnen van elk type zijn, bijv.: string, number, boolean … of een object. Bij voorkeur wordt een object type gebruikt die voor deze doeleinden zijn gemaakt, namelijk een Error (opens new window) object.

Een error object kan aangemaakt (instantie) worden via de Error constructor (met new keyword) of via Error() functie. Instanties van een Error objecten worden geworpen wanneer een runtime fout optreedt.

Een Error object kan als volgt aangemaakt worden:

const error1 = new Error("Can't fetch data from the server!");
1

Het Error bevat o.a. de eigenschappen message (de foutboodschap) en name (de naam van de fout).

Naast dit generiek (Eng. generic) Error object zijn er een aantal specifieke ingebouwde afgeleiden gemaakt, zoals: EvalError (opens new window), RangeError (opens new window), ReferenceError (opens new window), SyntaxError (opens new window), TypeError (opens new window) en URIError (opens new window).

# Foutafhandeling

Meestal wordt een Error object aangemaakt tijdens het werpen van een fout. Afhandelen van deze fout doen we via een try…catch statement:

try {
  throw new Error("We have an error!");
} catch (e) {
  console.error(e.name + ": " + e.message);
}
1
2
3
4
5

Extra info

Specifieke error typen kunnen apart afgehandeld worden door gebruik te maken van he instanceof keyword in combinatie met een conditioneel statement:

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.error(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.error(e.name + ": " + e.message);
  }
  // … etc
}
1
2
3
4
5
6
7
8
9
10

# Custom Error type

In JavaScript kunnen we ons eigengemaakte error typen creëren door over te erven van het Error object. In het voorbeeld maken we een custom klasse CustomError aan die overerft van het Error object. Deze custom error kan geworpen door throw new CustomError(); te implementeren:

class CustomError extends Error {
  constructor(foo = 'bar' ...params) {
    // Pass remaining arguments (including vendor specific ones) to parent constructor
    super(...params);

    // Maintains proper stack trace for where our error was thrown (only available on V8)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }

    this.name = 'CustomError';
    // Custom debugging information
    this.foo = foo;
    this.date = new Date();
  }
}

try {
  throw new CustomError('doe', 'This is an error message from John Doe!');
} catch(e){
	showErrorInConsole(e);
}

function showErrorInConsole (e) {
	if (e instanceof CustomError) {
		console.error(`${e.date.toTimeString()} | ${e.name} | ${e.message} | ${e.foo}`);
	} else {
		console.error(`${e.name} | ${e.message}`);
	}
}
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

Output:

"14:01:11 GMT+0200 (Midden-Europese zomertijd) | CustomError | This is an error message from John Doe! | doe"s
1

# Errors interpreteren

# Weergeven

In de realiteit zullen we veel vaker fouten lezen dan ze zelf te op te roepen. Instanties van het Error object worden meestal opgeroepen door ingebouwde of externe API’s, zoals bijvoorbeeld fetch en axios (opens new window).

fetch("/niet-bestaande-url")
  .then(function (response) {
    // Hier kan je iets doen met je data.
  })
  .catch(function (error) {
    console.log(error.message);
  });
1
2
3
4
5
6
7
axios.get('/niet-bestaande-url')
  .then(function (data) {
    // Hier kan je iets doen met je data.
  })
  .catch(function (error) {
    toast(`Er ging iets mis: ${error.message}`)
  }
1
2
3
4
5
6
7

Indien een API een foutmelding zal throwen zal je ook de message property kunnen aanspreken. Dit geeft ons dus nog een reden om het Error Object te gebruiken, zo zijn je eigen foutmeldingen overeenkomstig met de industriestandaard.

© 2025 Arteveldehogeschool Laatst bijgewerkt: 5/12/2023 13:41:16