Guide de gestion des exceptions dans Express PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Guide de la gestion des exceptions dans Express

Introduction

Des exceptions et des erreurs sont inévitables lorsque les utilisateurs interagissent avec n'importe quelle application, il appartient aux ingénieurs en logiciel de choisir un moyen de gérer toute erreur qui pourrait survenir - sciemment ou inconsciemment. Par conséquent, les développeurs backend qui créent des API avec Express doivent travailler pour s'assurer qu'ils créent une API utile, efficace et utilisable. Le plus important est de gérer les erreurs de manière à construire un système robuste, car cela permet de réduire le temps de développement, les erreurs pures et simples, les problèmes de productivité et détermine le succès ou l'évolutivité du développement logiciel.

Avez-vous besoin de consigner le message d'erreur, de supprimer l'erreur, d'informer les utilisateurs de l'erreur ou d'écrire du code pour gérer les erreurs ? Ne te demande plus.

Dans ce guide, nous apprendrons comment créer une base de code de gestion des erreurs robuste pour les applications Express, qui servira à aider à détecter les erreurs d'application et à prendre des mesures optimales pour récupérer toute application en cas d'échec gracieux pendant l'exécution.

Remarque: Nous utiliserons Postman pour tester l'API dans notre démo. Vous pouvez le télécharger sur le Page de téléchargement du facteur. Alternativement, vous pouvez simplement utiliser le navigateur, la ligne de commande curl outil, ou tout autre outil que vous connaissez peut-être.

Qu'est-ce que la gestion des erreurs ?

Dans le développement de logiciels, il existe deux types d'exceptions : opérationnel ainsi que programmatiques.

  • Des défaillances opérationnelles peuvent survenir pendant l'exécution, et afin d'empêcher l'application de se terminer brusquement, nous devons gérer ces exceptions avec élégance grâce à des méthodes efficaces de gestion des erreurs.
  • Les exceptions programmatiques sont lancées manuellement par un programmeur, lorsqu'un état exceptionnel survient.

Vous pouvez considérer les exceptions opérationnelles comme des exceptions « inattendues, mais prévues » (telles que l'accès à un index hors limites) et les exceptions programmatiques comme des exceptions « attendues et prévues » (telles qu'une exception de formatage des nombres).

La gestion des exceptions est la procédure utilisée pour trouver et corriger les défauts dans un programme. La gestion des erreurs envoie des messages qui incluent le type d'erreur qui s'est produit et la pile où l'erreur s'est produite.

Remarque: En informatique, les exceptions sont récupérables et découlent généralement de problèmes opérationnels ou de programmation pendant l'exécution. Les erreurs surviennent généralement à partir de facteurs externes, tels que des limitations matérielles, des problèmes de connectivité, un manque de mémoire, etc. En JavaScript, les termes sont souvent utilisés de manière interchangeable et les exceptions personnalisées sont dérivées du Error classer. le Error classe elle-même représente à la fois les erreurs et les exceptions.

Dans Express, la gestion des exceptions fait référence à la manière dont Express se configure pour intercepter et traiter les exceptions synchrones et asynchrones. L'avantage de la gestion des exceptions dans Express est qu'en tant que développeur, vous n'avez pas besoin d'écrire vos propres gestionnaires d'exceptions ; Express est livré avec un gestionnaire d'exceptions par défaut. Le gestionnaire d'exceptions aide à identifier les erreurs et à les signaler à l'utilisateur. Il fournit également diverses stratégies correctives et les met en œuvre pour atténuer les exceptions.

Bien que cela puisse sembler être beaucoup de choses sous le capot, la gestion des exceptions dans Express ne ralentit pas le processus global d'un programme ou ne suspend pas son exécution.

Comprendre la gestion des exceptions dans Express

Avec le gestionnaire d'erreurs par défaut fourni avec Express, nous avons entre nos mains un ensemble de fonctions middleware qui aident à détecter automatiquement les erreurs dans les gestionnaires de route. Bientôt, nous créerons un projet pour mettre la théorie en pratique sur la façon de renvoyer les erreurs appropriées dans une application Express et comment ne pas divulguer des informations sensibles.

Définition de la fonction middleware dans Express

Les fonctions du middleware de gestion des erreurs sont définies de manière à accepter une Error objet comme premier paramètre d'entrée, suivi des paramètres par défaut de toute autre fonction middleware : request, responseet nextL’ next() La fonction saute tous les middlewares actuels vers le gestionnaire d'erreurs suivant pour le routeur.

Configuration de la gestion des erreurs dans Express

Exécutez la commande suivante dans votre terminal pour créer une application Node et Express :

$ mkdir error-handling-express

Dans le dossier nouvellement créé, initialisons un nouveau projet Node :

$ cd error-handling-express && npm init -y

Cela crée un package.json fichier dans notre dossier.

Pour créer un serveur Express dans notre application Node, nous devons installer le express paquet, dotenv pour charger automatiquement les variables d'environnement dans .env déposer dans process.env objet, et nodemon pour redémarrer l'application de nœud si un changement de fichier est noté dans le répertoire.

$ npm install express dotenv nodemon

Ensuite, créez un app.js fichier dans le dossier du projet qui servira de fichier d'index pour l'application.

Maintenant que nous avons installé toutes les dépendances nécessaires pour notre application Express, nous devons configurer le script pour lire l'application dans le package.json dossier. Pour y parvenir, le package.json fichier, de sorte que le scripts l'objet est comme indiqué ci-dessous :

"scripts": {
    "start": "nodemon app.js"
},

Alternativement, vous pouvez sauter en utilisant nodemon, et utilise node app.js à la place.

Configurer un serveur Express

Pour configurer le serveur, nous devons d'abord importer les différents packages dans app.js. Nous créerons également un .env fichier dans le répertoire du projet – pour stocker toutes les variables d'environnement de l'application :



const express = require('express')
require('dotenv').config

PORT=4000 

Nous avons défini le numéro de port de l'application dans .env, qui est chargé et lu par dotenv, et peut être consulté ultérieurement.

Initialisation du serveur express

Maintenant, nous devons initialiser le serveur Express et faire en sorte que notre application écoute le numéro de port de l'application, ainsi qu'une demande à une route de test - /test. mettons à jour app.js, sous les instructions d'importation :


const app = express();
const port = process.env.PORT || 4000;

app.get("/test", async (req, res) => {
    return res.status(200).json({ success: true });
});

app.listen(port, () => {
    console.log(`Server is running at port ${port}`);
});

À partir de là, nous apprendrons à gérer les différents cas d'utilisation d'erreurs de fonctionnement pouvant être rencontrés, dans Express.

Gestion des erreurs introuvables dans Express

Supposons que vous ayez besoin d'extraire tous les utilisateurs d'une base de données d'utilisateurs, vous pouvez gérer efficacement un scénario d'erreur potentiel où aucune donnée n'existe dans la base de données, en enveloppant la logique dans un try/catch bloc - en espérant attraper toute erreur qui pourrait se projeter dans le catch bloquer:


const getUser = () => undefined;

app.get("/get-user", async (req, res) => {
	try {
		const user = getUser();
		if (!user) {
			throw new Error('User not found');
		}
	} catch (error) {
	    
		console.log(error); 
		
		res.status(400).send(error.message) 
	}
	return res.status(200).json({
		success: true
	});
});

Cela se traduit par:

User not found

Maintenant, lorsque cette demande est faite (vous pouvez tester en utilisant Postman) et qu'aucun utilisateur n'existe sur la base de données, le client reçoit un message d'erreur indiquant « Utilisateur introuvable ». De plus, vous remarquerez que l'erreur est également enregistrée dans la console.

Optimisation de la gestion des erreurs avec le middleware du gestionnaire d'erreurs

Nous pouvons optimiser le développement en créant un middleware de gestionnaire d'erreurs qui viendrait à la fin de toutes les routes définies, de sorte que si une erreur est lancée dans l'une des routes, Express jettera automatiquement un coup d'œil au middleware suivant et continuera à descendre la liste jusqu'à ce qu'il atteigne le gestionnaire d'erreurs. Le gestionnaire d'erreurs traitera l'erreur et renverra également une réponse au client.

Consultez notre guide pratique et pratique pour apprendre Git, avec les meilleures pratiques, les normes acceptées par l'industrie et la feuille de triche incluse. Arrêtez de googler les commandes Git et en fait apprendre il!

Pour commencer, créez un dossier appelé middleware dans le répertoire du projet, et dans ce dossier, créez un fichier appelé errorHandler.js qui définit le gestionnaire d'erreur :

const errorHandler = (error, req, res, next) => {
    
    console.log(error); 
    
    res.status(400).send(error.message); 
}
module.exports = errorHandler;

Dans notre fonction middleware, nous avons fait prendre conscience à Express qu'il ne s'agit pas d'une fonction middleware de base, mais d'un gestionnaire d'erreurs, en ajoutant le error paramètre avant les 3 paramètres de base.

Maintenant, nous allons utiliser le gestionnaire d'erreurs dans notre démo app.js et gérez l'erreur initiale de récupération des utilisateurs avec le middleware du gestionnaire d'erreurs, comme illustré ci-dessous :


const getUser = () => undefined;

app.get("/get-user", async (req, res, next) => {
	try {
		const user = getUser();
		if (!user) {
			throw new Error("User not found");
		}
	} catch (error) {
		return next(error);
	}
});

app.use(errorHandler);

Nous pouvons encore optimiser notre code, en créant une abstraction autour du try/catch logique. Nous pouvons y parvenir en créant un nouveau dossier dans le répertoire du projet appelé utils, et dedans, créez un fichier appelé tryCatch.js.

Pour abstraire le try-catch logique - nous pouvons définir une fonction qui accepte une autre fonction (connue sous le nom de contrôleur) comme paramètre, et renvoie un async fonction qui tiendra un try/catch pour tout contrôleur reçu.

Si une erreur se produit dans le contrôleur, elle est capturée dans le catch bloc et la fonction suivante est appelée :


const tryCatch = (controller) => async (req, res, next) => {
	try {
		await controller(req, res);
	} catch (error) {
		return next(error);
	}
};
module.exports = tryCatch;

Avec la try/catch abstraction, nous pouvons refactoriser notre code pour le rendre plus succint en sautant le try-catch clause explicitement lors de la récupération des utilisateurs dans le app.js:


const getUser = () => undefined;

app.get(
	"/get-user",
	tryCatch(async (req, res) => {
		const user = getUser();
		if (!user) {
			throw new Error("User not found");
		}
		res.status(400).send(error.message);
	})
);

Nous avons réussi à faire abstraction de la logique try-catch et notre code fonctionne toujours comme avant.

Gestion des erreurs de validation dans Express

Pour cette démo, nous allons créer un nouvel itinéraire dans notre application Express pour la connexion - pour valider un ID utilisateur lors de la connexion. Tout d'abord, nous allons installer le joi package, pour aider à créer un schéma, avec lequel nous pouvons appliquer les exigences :

$ npm i joi

Ensuite, créez un schéma qui est un Joi.object avec une userId qui doit être un nombre et est obligatoire - ce qui signifie que la demande doit correspondre à un objet avec un ID utilisateur dessus.

Nous pouvons utiliser le validate() méthode dans l'objet de schéma pour valider chaque entrée par rapport au schéma :


const schema = Joi.object({
	userId: Joi.number().required(),
});

app.post(
	"/login",
	tryCatch(async (req, res) => {
		const {error, value} = schema.validate({});
		if (error) throw error;
	})
);

Si un objet vide est passé dans le validate() méthode, l'erreur serait gérée avec élégance et le message d'erreur serait envoyé au client :

Sur la console, on a également accès à un details tableau qui comprend divers détails sur l'erreur qui pourraient être communiqués à l'utilisateur le cas échéant.

Pour gérer spécifiquement les erreurs de validation de manière à transmettre le détail d'erreur approprié par erreur de validation, le middleware du gestionnaire d'erreurs peut être refactorisé :


const errorHandler = (error, req, res, next) => {
	console.log(error); 

	if (error.name === "ValidationError") {
		return res.status(400).send({
			type: "ValidationError",
			details: error.details,
		});
	}

	res.status(400).send(error.message); 
};

module.exports = errorHandler;

Avec errorHandler.js maintenant personnalisé, lorsque nous faisons la même requête avec un objet vide passé au validate() méthode:

Guide de gestion des exceptions dans Express PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Nous avons maintenant accès à un objet personnalisé qui renvoie les messages de manière plus lisible/conviviale. De cette façon, nous sommes en mesure d'envoyer et de gérer différents types d'erreurs en fonction du type d'erreur entrant.

Conclusion

Dans ce guide, nous avons passé en revue tous les aspects de la gestion des erreurs d'Express.js, y compris la façon dont le code synchrone et asynchrone est géré par défaut, comment créer vos propres classes d'erreurs, comment écrire des fonctions middleware de gestion des erreurs personnalisées et fournir next en tant que gestionnaire de capture finale

Comme pour toutes les tâches, il existe également des bonnes pratiques lors du développement qui incluent une gestion efficace des erreurs, et aujourd'hui nous avons appris comment nous pouvons gérer les erreurs dans une application Express de manière robuste.

Gérer correctement les erreurs ne signifie pas seulement réduire le temps de développement en trouvant facilement les bogues et les erreurs, mais aussi développer une base de code robuste pour les applications à grande échelle. Dans ce guide, nous avons vu comment mettre en place un middleware pour gérer les erreurs de fonctionnement. Parmi les autres moyens d'améliorer la gestion des erreurs, citons : ne pas envoyer de traces de pile, arrêter les processus en douceur pour gérer les exceptions non interceptées, fournir des messages d'erreur appropriés, envoyer des journaux d'erreurs et configurer une classe qui étend le Error classe.

J'espère que les exemples que j'ai utilisés dans ce tutoriel vous ont plu. J'ai couvert divers scénarios que vous pourriez potentiellement rencontrer lors de l'écriture d'une application Express à utiliser dans le monde réel concernant la gestion des erreurs. S'il vous plaît, faites-moi savoir s'il y a quelque chose que j'ai manqué. Cela nous sera bénéfique et m'aidera également à en apprendre davantage. Bonne journée et merci d'avoir lu.

Vous pouvez vous référer à tout le code source utilisé dans l'article sur Github.

Ressources additionnelles

Horodatage:

Plus de Stackabuse