Erreurs personnalisées, extension d’erreur

Lorsque nous développons quelque chose, nous avons souvent besoin de nos propres cours d’erreur pour refléter des choses spécifiques qui peuvent se tromper dans nos tâches. Pour les erreurs dans les opérations de réseau, nous pouvons avoir besoin HttpError, pour les opérations de base de données , pour les opérations de recherche NotFoundError, etc.

Nos erreurs doivent prendre en charge les propriétés d’erreur de base tels que message name et, de préférence, stack. Mais ils peuvent également avoir d’autres propriétés propres, par exemple, des objets HttpError peuvent avoir une propriété statusCode avec une valeur que ou 403 ou

ou 500

JavaScript vous permet d’utiliser throw avec un argument, donc techniquement nos classes d’erreur personnalisées ne ont pas besoin d’hériter de Error. Mais si nous héritons, il est alors possible d’utiliser

pour identifier l’erreur d’objets. Ensuite, il vaut mieux hériter de lui.

Au fur et à mesure que l’application se développe, nos propres erreurs forment naturellement une hiérarchie. Par exemple, HttpTimeoutError peut hériter de HttpError, et ainsi de suite.

EURRUT

à titre d’exemple, considérons une fonction qui devrait lire JSON avec les données de l’utilisateur.

Voici un exemple de la façon dont un valide:

En interne, nous utiliserons JSON.parse. Si vous recevez mal formé, puis jetez SyntaxError. Mais même si est syntaxiquement correct, cela ne signifie pas qu’il s’agit d’un utilisateur valide, non? Vous pouvez perdre les données nécessaires. Par exemple, vous ne pouvez pas avoir de propriétés de nom et d’âge essentielles à nos utilisateurs.

Notre fonction readUser(json) va non seulement lire JSON, mais vérifiera ( » Valider « ) les données. S’il n’y a pas de champs obligatoires, ou le format est incorrect, il est une erreur. et ce n’est pas un » SyntaxError », car les données sont syntaxiquement correct, mais un autre type d’erreur. Nous allons appeler ValidationError et créer une classe pour cela. Une erreur de ce type doit également apporter les informations sur le champ minéral.

Notre classe ValidationError devrait hériter de la classe intégrée

ce genre est incorporé, mais voici votre code approximatif afin que nous puissions comprendre ce que nous étendons.

// El "pseudocódigo" para la clase Error incorporada definida por el propio JavaScriptclass Error { constructor(message) { this.message = message; this.name = "Error"; // (diferentes nombres para diferentes clases error incorporadas) this.stack = <call stack>; // no estándar, pero la mayoría de los entornos lo admiten }}

maintenant , nous allons Hériter ValidationError et le prouver en action:

class ValidationError extends Error { constructor(message) { super(message); // (1) this.name = "ValidationError"; // (2) }}function test() { throw new ValidationError("Vaya!");}try { test();} catch(err) { alert(err.message); // Vaya! alert(err.name); // ValidationError alert(err.stack); // una lista de llamadas anidadas con números de línea para cada una}

Remarque: Sur la ligne (1) Nous appelons le bâtisseur père. JavaScript nécessite que nous appelions super dans le constructeur de fils, il est donc obligatoire. Le constructeur parent définit la propriété message.

Le constructeur principal définit également la propriété name dans "Error", donc sur la ligne (2) Réinitialisez-le à la valeur correcte.

Essayez de l’utiliser dans readUser(json)

class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; }}// Usofunction readUser(json) { let user = JSON.parse(json); if (!user.age) { throw new ValidationError("Sin campo: age"); } if (!user.name) { throw new ValidationError("Sin campo: name"); } return user;}// Ejemplo de trabajo con try..catchtry { let user = readUser('{ "age": 25 }');} catch (err) { if (err instanceof ValidationError) { alert("Dato inválido: " + err.message); // Dato inválido: sin campo: nombre } else if (err instanceof SyntaxError) { // (*) alert("Error de sintaxis JSON: " + err.message); } else { throw err; // error desconocido, vuelva a lanzarlo (**) }}

le bloc try..catch Dans les poignées de code précédent à la fois notre ValidationError comme SyntaxError intégré JSON.parse.

Remarquez comment instanceof pour vérifier le type de spécifique d’erreur sur le (*)

on pourrait regarder aussi err.name, comme ceci:

// ...// en lugar de (err instanceof SyntaxError)} else if (err.name == "SyntaxError") { // (*)// ...

instanceof est beaucoup mieux, parce que dans l’avenir , nous allons étendre , nous ferons des sous-types de celui-ci, comme PropertyRequiredError. Et contrôle continuera de fonctionner pour de nouvelles classes héritées. Ensuite, qui va à l’avenir.

Il est également important que si catch trouver une erreur inconnue, il re-jeter sur la ligne (**). Le bloc ne savoir comment gérer la validation et des erreurs de syntaxe, d’ autres types ( en raison d’une erreur typographique dans le code ou d’ autres étrangers) doit échouer.

supplémentaires Héritage

Classe ValidationError est très générique. Beaucoup de choses peuvent aller mal.La propriété peut être absente ou peut être dans un format incorrect (comme valeur de chaîne pour age). Faisons une classe plus concrète PropertyRequiredError, exactement pour les propriétés absentes. Il faudra des informations supplémentaires sur la propriété manquante.

la nouvelle classe PropertyRequiredError est facile à utiliser: il suffit de passer le nom de la propriété: new PropertyRequiredError(property) . L’ID

Lisible humain est généré par le constructeur.

Veuillez noter que this.name dans le constructeur PropertyRequiredError est attribué à nouveau manuellement. Cela peut devenir un peu fastidieux: assigner this.name = <class name> dans chaque classe d’erreur personnalisée. Nous pouvons l’éviter en faisant notre propre classe « Erreur de base » qui attribue this.name = this.constructor.name. Puis hériter toutes nos erreurs personnalisées.

Appelons-le MyError

Voici le code avec MyError et d’ autres classes personnalisées, erreur simplifiée:

Les erreurs personnalisées sont beaucoup plus courtes, surtout ValidationError, puisque nous supprimons la ligne "this.name = ..." dans le constructeur.

EXCELDÉ DES EXCEPTIONS

Le but de la fonction readUser dans le code précédent est « Lire les données de l’utilisateur ». Il peut y avoir différents types d’erreurs dans le processus. A ce moment-là, nous avons SyntaxError et

et

« ca4dc42d43 »>

, mais à l’avenir, la fonction readUser peut Cultiver et générer probablement d’autres types d’erreurs.

Le code qui appelle readUser doit gérer ces erreurs. A ce moment-là, il utilise plusieurs if dans le bloc catch, qui vérifie la classe et gérez les erreurs connues et jetez à nouveau les étrangers.

Le schéma est comme ceci:

> Dans le code précédent, nous pouvons voir deux types d’erreurs, mais il peut y avoir plus.

si la fonction readUser génère divers types d’erreurs, puis nous devons Demandez-nous: nous voulons vraiment vérifier tous les types d’erreur un par une à chaque fois?

Souvent, la réponse est « Non »: nous aimerions être « un niveau supérieur à tout ce qui ». Nous voulons seulement savoir s’il y avait une « erreur de lecture de données »: pourquoi cela est arrivé exactement est souvent sans importance (le message d’erreur le décrit). Ou mieux, nous aimerions avoir un moyen d’obtenir les détails de l’erreur, mais seulement si nécessaire.

La technique que nous avons décrite ici est appelée « exceptions d’emballage ».

  1. Nous allons créer une nouvelle classe ReadError Pour représenter une erreur générique de « lecture de données ».
  2. La fonction readUser détectera les erreurs de lecture de données qui se produisent en lui, comme ValidationError et SyntaxError et génère un ReadError L’objet ReadError conservera la référence d’erreur d’origine sur votre propriété cause.

alors, le code qui appelle readUser ne doit avoir à vérifier que ReadError, pas tous les types d’erreurs de lecture D Atos Et si vous avez besoin de plus de détails d’une erreur, vous pouvez vérifier votre propriété cause.

Voici le code qui définit ReadError et il démontre son utilisation dans readUser et

« 3AB1F3B34D »>

:

class ReadError extends Error { constructor(message, cause) { super(message); this.cause = cause; this.name = 'ReadError'; }}class ValidationError extends Error { /*...*/ }class PropertyRequiredError extends ValidationError { /* ... */ }function validateUser(user) { if (!user.age) { throw new PropertyRequiredError("age"); } if (!user.name) { throw new PropertyRequiredError("name"); }}function readUser(json) { let user; try { user = JSON.parse(json); } catch (err) { if (err instanceof SyntaxError) { throw new ReadError("Error de sintaxis", err); } else { throw err; } } try { validateUser(user); } catch (err) { if (err instanceof ValidationError) { throw new ReadError("Error de validación", err); } else { throw err; } }}try { readUser('{json malo}');} catch (e) { if (e instanceof ReadError) { alert(e); // Error original: SyntaxError: inesperado token b en JSON en la posición 1 alert("Error original: " + e.cause); } else { throw e; }}

dans le code précédent, readUser Travaux Exactement en tant que SE décrivent: détecte les erreurs de syntaxe et de validation et jette les erreurs ReadError (erreurs inconnues est générée comme d’habitude).

alors, le code externe vérifie instanceof ReadError et c’est tout. Il n’est pas nécessaire de répertorier tous les types d’erreur possibles.

L’accent est appelé « Exceptions d’emballage », car nous prenons des exceptions « bas niveau » et « ajuster » dans ReadError qui est plus abstrait. Il est largement utilisé dans la programmation orientée objet.

Résumé

  • Nous pouvons hériter de Error et d’autres classes d’erreur gentiment intégrées. Nous n’avons besoin que de prendre soin de la propriété name et n’oubliez pas d’appeler super.
  • Nous pouvons utiliser pour vérifier les erreurs particulières. Cela fonctionne également avec héritage.Mais parfois, nous avons un objet d’erreur qui provient d’une bibliothèque tiers et il n’y a pas de moyen facile d’obtenir sa classe. Ensuite, la propriété peut être utilisée pour de tels contrôles.
  • EXCEPTIONS PACKET est une technique généralisée: une fonction gère des exceptions de bas niveau et crée des erreurs de haut niveau dans Lieu de plusieurs erreurs de faible niveau. Les exceptions de faible niveau sont parfois converties en propriétés de cet objet comme err.cause dans les exemples précédents, mais ce n’est pas strictement nécessaire.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *