Maison > interface Web > js tutoriel > Comment créer un émetteur d'événements prioritaires personnalisé dans Node.js

Comment créer un émetteur d'événements prioritaires personnalisé dans Node.js

Susan Sarandon
Libérer: 2024-12-20 16:05:11
original
1060 Les gens l'ont consulté

How to Create a Custom Priority Event Emitter in Node.js

Installation:

Installation et configuration des bibliothèques

npm i -d @types/node tsx typescript
npx tsc --init
Copier après la connexion
Copier après la connexion

Modifiez tsconfig.json et package.json

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "ES6",
    "moduleResolution": "nodenext",
    "allowImportingTsExtensions": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "outDir": "./dist",
    "types": ["node"]
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

// package.json
{
  "name": "node-starter",
  "version": "0.0.0",
  "type": "module", // This should be set to "module" for using ES6 modules
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "@types/jest": "^29.5.14",
    "jest": "^29.7.0",
    "typescript": "^5.7.2"
  },
  "dependencies": {
    "@types/node": "^22.10.2",
    "tsx": "^4.19.2"
  }
}
Copier après la connexion
Copier après la connexion

Comprendre EventEmitter dans Node.js

Node.js utilise EventEmitter comme classe fondamentale pour gérer les événements dans la programmation asynchrone. Cette classe vous permet d'enregistrer des auditeurs pour des événements spécifiques et d'émettre ces événements en cas de besoin. Par défaut, EventEmitter traite les événements dans l'ordre dans lequel les écouteurs ont été ajoutés. Cependant, nous pouvons parfois souhaiter donner la priorité à l’exécution de certains auditeurs par rapport à d’autres. C'est là que nous pouvons introduire un système d'événements basé sur les priorités.

Étapes pour créer un émetteur d'événements prioritaire

  1. Héritage de EventEmitter :
    Pour créer un émetteur d'événements personnalisé avec gestion des priorités, nous devons étendre la classe EventEmitter intégrée. Cela nous donne accès à toutes les méthodes intégrées comme on, émettre et supprimerListener.

    import EventEmitter from 'events';
    
    export class PriorityEmitter extends EventEmitter {
      private _listeners: Record<
        string,
        { listener: (...args: any[]) => void; priority: number }[]
      >;
    
      constructor() {
        super();
        this._listeners = {};
      }
    }
    
    Copier après la connexion
- `PriorityEmitter` extends `EventEmitter`, so it inherits all of its functionality.
- We introduce a new internal property `_listeners` to store listeners along with their priorities.
Copier après la connexion
  1. Remplacement de la méthode on :
    En remplaçant la méthode on, nous pouvons ajouter une logique personnalisée pour stocker les auditeurs avec leurs priorités et les trier en fonction de leur priorité.

    on(event: string, listener: (...args: any[]) => void, priority = 0) {
      if (!this._listeners[event]) this._listeners[event] = [];
      this._listeners[event].push({ listener, priority });
      this._listeners[event].sort((a, b) => b.priority - a.priority);
      return this;
    }
    
    Copier après la connexion
- For production usage, consider using other data structures instead of arrays, which maintain order.
- When a listener is added using `on`, we push the listener and its priority into the `_listeners` array.
- We then sort the listeners in descending order based on the priority. This ensures that higher-priority listeners are executed first.
- The default priority is `0` if not specified.
Copier après la connexion
  1. Remplacer la méthode d'émission :
    La méthode submit déclenche l'événement et exécute les écouteurs. Dans la méthode remplacée, nous traitons d'abord les auditeurs de _listeners en fonction de leur priorité.

    emit(event: string, ...args: any[]) {
      if (this._listeners[event]) {
        for (const { listener } of this._listeners[event]) {
          listener(...args);
        }
      }
      return super.emit(event, ...args);
    }
    
    Copier après la connexion
- For the given event, we iterate over the sorted listeners and call each listener.
- After handling the custom priority-based logic, we call the parent class’s `emit` method to ensure the standard behavior is also preserved.
Copier après la connexion
  1. Remplacement de la méthode removeListener :
    La méthode removeListener est remplacée pour garantir que les écouteurs sont correctement supprimés en fonction de leur référence. Puisque nous stockons les auditeurs avec leurs priorités, nous filtrons le bon auditeur.

    removeListener(event: string, listener: (...args: any[]) => void) {
      if (this._listeners[event]) {
        this._listeners[event] = this._listeners[event].filter(
          (stored_listener) => stored_listener.listener !== listener
        );
      }
      super.removeListener(event, listener);
      return this;
    }
    
    Copier après la connexion
- We filter the listener array to remove the listener with the exact reference.
- Then we call `super.removeListener` to ensure proper cleanup and avoid memory leaks.
Copier après la connexion

Comment fonctionne le PriorityEmitter

  • Lorsqu'un événement est émis, les auditeurs sont invoqués par ordre de priorité. Plus la priorité est élevée, plus il sera exécuté tôt.
  • Les auditeurs avec une priorité égale sont exécutés dans l'ordre dans lequel ils ont été ajoutés.

Exemple d'utilisation

Voici un exemple pour démontrer comment fonctionne le PriorityEmitter dans la pratique :

const pe = new PriorityEmitter();

// Listener with higher priority
pe.on('greet', (name: string) => {
  console.log(`Hello ${name}!`);
}, 2);

// Listener with lower priority
pe.on('greet', (name: string) => {
  console.log(`Hi, ${name}!`);
}, 1);

// Emitting the event
pe.emit('greet', 'Alice');
Copier après la connexion

Sortie :

npm i -d @types/node tsx typescript
npx tsc --init
Copier après la connexion
Copier après la connexion
  • L'auditeur de priorité 2 (Bonjour Alice !) est appelé en premier.
  • L'auditeur de priorité 1 (Salut Alice !) est appelé ensuite.

Considérations relatives aux performances

  • Choix de la structure des données : Dans cet exemple de base, nous utilisons un tableau pour stocker les écouteurs et les trier à chaque fois qu'un écouteur est ajouté. Cela peut devenir inefficace lorsqu’il y a un grand nombre d’auditeurs. Une meilleure solution pour gérer les priorités dans un environnement où les performances sont critiques serait d'utiliser un tas maximum, qui permet des opérations d'insertion et de suppression efficaces.
  • Utilisation en production : pour les applications de niveau production, envisagez d'utiliser des structures de données plus avancées ou des bibliothèques externes qui fournissent des files d'attente prioritaires pour gérer plus efficacement un grand nombre d'événements.

Code complet

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "ES6",
    "moduleResolution": "nodenext",
    "allowImportingTsExtensions": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "outDir": "./dist",
    "types": ["node"]
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

// package.json
{
  "name": "node-starter",
  "version": "0.0.0",
  "type": "module", // This should be set to "module" for using ES6 modules
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "@types/jest": "^29.5.14",
    "jest": "^29.7.0",
    "typescript": "^5.7.2"
  },
  "dependencies": {
    "@types/node": "^22.10.2",
    "tsx": "^4.19.2"
  }
}
Copier après la connexion
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal