Module Domain de Node.js
Le module Domain est un outil dans Node.js pour simplifier la gestion des erreurs dans le code asynchrone. Il vous permet de regrouper plusieurs opérations asynchrones dans un "domain" et de capturer et gérer uniformément les erreurs au sein de ce domaine.
En termes simples, Domain est comme un "conteneur" de gestion des erreurs. Vous pouvez placer des opérations asynchrones liées dans ce conteneur, puis gérer uniformément les erreurs susceptibles de survenir dans ces opérations.
L'utilisation du module domain est dépréciée dans Node.js 14, car la communauté Node.js recommande des méthodes plus modernes pour gérer les erreurs, comme l'utilisation d'async/await ou d'une logique plus complète d'écoute et de gestion des erreurs.
Pourquoi avez-vous besoin du module Domain ?
Dans la programmation asynchrone Node.js, la gestion des erreurs peut devenir complexe :
- Les erreurs asynchrones sont difficiles à intercepter: Le try-catch traditionnel ne peut pas intercepter les erreurs dans les callbacks asynchrones
- La propagation des erreurs est difficile: Les erreurs peuvent se produire dans n'importe quelle opération asynchrone, ce qui rend difficile l'identification de la source
- Problèmes de nettoyage des ressources: Après la survenue d'une erreur, vous devez vous assurer que les ressources sont libérées correctement
Le module Domain est conçu pour résoudre ces problèmes.
Concepts fondamentaux du module Domain
1. Création d'un Domain
Exemple
const myDomain = domain.create();
2. Cycle de vie d'un Domain
- Création: Utiliser
domain.create() - Entrée: Utiliser
domain.enter()ou entrer implicitement - Exécution: exécuter du code dans le domaine
- Sortie: utiliser
domain.exit() - Destruction: automatiquement détruit lorsqu'il n'y a plus de références
3. Liaison implicite
Un Domain peut être implicitement lié aux objets suivants :
setTimeout/setIntervalFonctions de rappel- Événements EventEmitter
- Opérations sur les flux
Méthodes principales de Domain
1. domain.run(fn)
Exécuter une fonction dans le contexte du domaine :
Exemple
// Les opérations asynchrones ici seront interceptées par le domain
setTimeout(() => {
throw new Error('Async error');
}, 100);
});
2. domain.add(emitter)
Ajoutez explicitement une instance EventEmitter au domain :
Exemple
myDomain.add(server);
3. domain.remove(emitter)
Supprimez une instance EventEmitter du domain.
4. domain.bind(callback)
Renvoie une nouvelle fonction liée au domain :
Exemple
if (err) throw err;
console.log(data);
});
5. domain.intercept(callback)
Similaire à bind, mais gère spécifiquement les callbacks error-first:
Exemple
console.log(data);
});
Gestion des erreurs
Domain gère les erreurs capturées viaerrorl'événement error:
Exemple
console.error('Domain caught error:', err);
// Nettoyer les ressources
server.close();
});
Exemples d’application pratique
1. Gestion des erreurs du serveur HTTP
Exemple
const domain = require('domain');
const server = http.createServer((req, res) => {
const d = domain.create();
d.on('error', (err) => {
res.statusCode = 500;
res.end(`Server error: ${err.message}`);
// Empêcher le plantage du processus
server.close();
});
d.run(() => {
// Gérer la requête
process.nextTick(() => {
// Simuler une erreur asynchrone
if (req.url === '/error') {
throw new Error('Erreur intentionnelle');
}
res.end('OK');
});
});
});
server.listen(3000);
2. Gestion des connexions à la base de données
Exemple
const db = require('some-db-library');
function queryDatabase(callback) {
const d = domain.create();
d.on('error', (err) => {
console.error('Erreur de base de données :', err);
db.releaseConnection();
});
d.run(() => {
db.getConnection((err, connection) => {
if (err) throw err;
connection.query('SELECT * FROM users', (err, results) => {
if (err) throw err;
callback(null, results);
db.releaseConnection();
});
});
});
}
Limites de Domain
- Déprécié: Node.js a officiellement déprécié le module domain ; il est recommandé d'utiliser async_hooks ou d'autres méthodes
- Fuites de mémoire: Une utilisation incorrecte peut entraîner des fuites de mémoire
- Surcoût de performance: La création et la gestion de domaines entraînent un certain surcoût de performance
Alternatives
Étant donné que le module domain a été déprécié, envisagez les alternatives suivantes :
- async/await + try-catch: Utilisez des méthodes modernes de traitement asynchrone en JavaScript
- Gestion des erreurs Promise: Utilisez
.catch()pour gérer les erreurs dans les chaînes Promise - async_hooks: Une API de suivi de contexte asynchrone de plus bas niveau fournie par Node.js
Méthodes et propriétés
| Méthode/Propriété | Description |
|---|---|
domain.create() | Créer et renvoyer un nouveaudomaininstance. |
domain.run(callback) | Exécuter la fonction de rappel fournie dans le domaine, en interceptant automatiquement les erreurs dans la fonction de rappel. |
domain.bind(callback) | Créer une nouvelle fonction qui appelle la fonction d'origine, tout en interceptant toute erreur levée. |
domain.intercept(callback) | Similaire àbind(), mais transmet l'erreur comme premier argument à la fonction de rappel. |
domain.add(emitter) | Ajouter explicitement un objet EventEmitter ou Timer afin que ses erreurs soient interceptées par le domaine actuel. |
domain.remove(emitter) | Supprimer l'objet EventEmitter ou Timer spécifié du domaine. |
domain.on('error', callback) | Écouter l'événement du domaineerror, en interceptant toutes les erreurs non gérées. |
Exemple
1. Créer un domaine et utiliser domain.run() pour intercepter les erreurs
domain.run() peut placer des opérations asynchrones dans le domaine ; si une erreur se produit dans l'opération, elle sera interceptée et gérée par le domaine actuel.
Exemple
const d = domain.create();
d.on('error', (err) => {
console.log('Erreur interceptée :', err);
});
d.run(() => {
setTimeout(() => {
throw new Error('Erreur asynchrone');
}, 100);
});
Dans l'exemple ci-dessus, l'erreur dans setTimeout est capturée par l'événement error du domaine, sans provoquer le plantage du processus.
2. Utilisez domain.bind() pour intercepter les erreurs dans les callbacks
domain.bind() crée une fonction d'encapsulation qui peut intercepter les erreurs de la fonction de rappel dans le domaine courant.
Exemple
const d = domain.create();
d.on('error', (err) => {
console.log('Erreur interceptée :', err);
});
const asyncFunction = d.bind((callback) => {
setTimeout(() => {
callback(new Error('Error in callback'));
}, 100);
});
asyncFunction((err) => {
if (err) throw err;
});
Ici, l'erreur dans asyncFunction sera interceptée et gérée par le domaine.
3. Utilisez domain.add() pour ajouter explicitement des événements
Vous pouvez utiliser domain.add() pour ajouter un EventEmitter spécifique au domaine, afin que ses erreurs soient également interceptées par le domaine.
Exemple
const EventEmitter = require('events');
const d = domain.create();
const emitter = new EventEmitter();
d.on('error', (err) => {
console.log('Caught EventEmitter error:', err);
});
// Ajouter emitter au domaine
d.add(emitter);
emitter.on('data', () => {
throw new Error('Error in EventEmitter');
});
emitter.emit('data');
Lorsque l'événement data lève une erreur, le domain intercepte cette erreur sans provoquer le plantage du programme.
Notes et limitations de domain
- Impact sur les performances:
domainCela aura un certain impact sur les performances, en particulier dans les scénarios à forte concurrence, donc une utilisation fréquente n'est pas recommandée. - Non recommandé pour une utilisation dans de nouveaux projets: Depuis Node.js 4.0,
domaina été marqué comme un module obsolète. Pour les nouveaux projets, il est recommandé d'utiliser des méthodes de gestion des erreurs plus modernes, telles queasync/await、try/catchet les écouteurs d'événements, etc. - Ne convient pas à tous les scénarios:
domainIl ne peut pas intercepter tous les types d'erreurs (comme les erreurs de syntaxe) ; il ne convient qu'à la gestion des erreurs d'exécution dans les opérations asynchrones et les fonctions de rappel.
Alternatives
Puisquedomaina été déprécié, il est recommandé d'utiliser les méthodes suivantes pour gérer les erreurs dans les opérations asynchrones :
- Utiliser
async/awaitettry/catch: Pour les fonctions qui prennent en charge async/await, les erreurs peuvent être interceptées viatry/catch. - Gestion globale des erreurs: Vous pouvez utiliser
process.on('uncaughtException')etprocess.on('unhandledRejection')pour écouter les exceptions non capturées et les rejets de Promise non gérés. - Gestion des erreurs pour les écouteurs d'événements: Ajoutez un écouteur à chaque EventEmitter
errorévénement.
Bien quedomainLe module offre un moyen pratique d'intercepter les erreurs dans les opérations asynchrones, mais en raison de problèmes de performance et de fiabilité, Node.js ne recommande pas officiellement de l'utiliser dans de nouveaux projets. Pour la gestion des exceptions, il est recommandé d'utiliser des solutions plus modernes, telles queasync/awaitet les écouteurs d'événements pour garantir que les erreurs peuvent être gérées efficacement dans l'application.
Modules intégrés de Node.js