npm i -d @types/node tsx typescript npx tsc --init
// 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" } }
Node.js 使用 EventEmitter 作为异步编程中处理事件的基础类。此类允许您注册特定事件的侦听器并在需要时发出这些事件。默认情况下,EventEmitter 按照添加侦听器的顺序处理事件。然而,有时我们可能希望优先执行某些侦听器而不是其他侦听器。这就是我们可以引入基于优先级的事件系统的地方。
继承自EventEmitter:
要创建具有优先级处理功能的自定义事件发射器,我们需要扩展内置的 EventEmitter 类。这使我们能够访问所有内置方法,例如 on、emit 和 removeListener。
import EventEmitter from 'events'; export class PriorityEmitter extends EventEmitter { private _listeners: Record< string, { listener: (...args: any[]) => void; priority: number }[] >; constructor() { super(); this._listeners = {}; } }
- `PriorityEmitter` extends `EventEmitter`, so it inherits all of its functionality. - We introduce a new internal property `_listeners` to store listeners along with their priorities.
重写 on 方法:
通过重写 on 方法,我们可以添加自定义逻辑来存储侦听器及其优先级,并根据其优先级对它们进行排序。
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; }
- 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.
重写发射方法:
emit 方法触发事件并执行侦听器。在重写的方法中,我们首先根据优先级处理 _listeners 中的侦听器。
emit(event: string, ...args: any[]) { if (this._listeners[event]) { for (const { listener } of this._listeners[event]) { listener(...args); } } return super.emit(event, ...args); }
- 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.
重写removeListener方法:
重写removeListener方法以确保根据引用正确删除侦听器。由于我们存储侦听器及其优先级,因此我们过滤掉了正确的侦听器。
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; }
- 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.
这是一个演示 PriorityEmitter 在实践中如何工作的示例:
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');
输出:
npm i -d @types/node tsx typescript npx tsc --init
// 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" } }
以上是如何在 Node.js 中创建自定义优先级事件发射器的详细内容。更多信息请关注PHP中文网其他相关文章!