Node.js에서 발생하는 모든 이벤트 수신
Node.js 에서 EventEmitter 객체 가 내 보낸 모든 이벤트 를 수신 할 수있는 방법이 있습니까?
예를 들어, 다음과 같이 할 수 있습니까?
event_emitter.on('',function(event[, arg1][, arg2]...) {}
아이디어는 서버 측 EventEmitter
에서 뱉어 낸 모든 이벤트 JSON.stringify
, 이벤트 데이터를 가져 와서 웹 소켓 연결을 통해 보내고, 클라이언트 측에서 이벤트로 재구성 한 다음 클라이언트 측에서 이벤트에 대해 조치를 취하고 싶습니다. .
언급했듯이이 동작은 node.js 코어에 없습니다. 그러나 hij1nx의 EventEmitter2를 사용할 수 있습니다.
https://github.com/hij1nx/EventEmitter2
EventEmitter를 사용하여 기존 코드를 손상시키지 않지만 네임 스페이스 및 와일드 카드에 대한 지원을 추가합니다. 예를 들면 :
server.on('foo.*', function(value1, value2) {
console.log(this.event, value1, value2);
});
나는 이것이 조금 오래되었다는 것을 알고 있지만 도대체 여기에 다른 해결책이 있습니다.
모든 이벤트를 잡으려는 이미 터의 emit 함수를 쉽게 원숭이 패치 할 수 있습니다.
function patchEmitter(emitter, websocket) {
var oldEmit = emitter.emit;
emitter.emit = function() {
var emitArgs = arguments;
// serialize arguments in some way.
...
// send them through the websocket received as a parameter
...
oldEmit.apply(emitter, arguments);
}
}
이것은 매우 간단한 코드이며 모든 이미 터에서 작동합니다.
ES6 수업을 사용하면 매우 쉽습니다.
class Emitter extends require('events') {
emit(type, ...args) {
console.log(e + " emitted")
super.emit(type, ...args)
}
}
위에서 설명한 모든 솔루션이 작동 할 수 있다는 점에 유의하십시오. node.js EventEmitter 내부 구현을위한 일종의 해킹이 수반됩니다.
이 질문에 대한 정답은 다음과 같습니다 . 기본 EventEmitter 구현이이를 지원하지 않으므로 해킹해야합니다 .
EventEmitter에 대한 node.js 소스 코드를 살펴보면 특정 이벤트 유형에 리스너가 연결되어 있지 않으면 해시에서 콜백 함수를 검색하려고하기 때문에 추가 작업없이 반환됩니다. 이벤트 유형에 따라 :
https://github.com/nodejs/node/blob/98819dfa5853d7c8355d70aa1aa7783677c391e5/lib/events.js#L176-L179
그렇기 때문에 다음과 같은 것이 eventEmitter.on('*', ()=>...)
기본적으로 작동하지 않습니다.
이것은 Martin이 위에서 제공 한 답변을 기반으로합니다. 나는 노드에 약간 익숙하기 때문에 그의 대답을 스스로 해결해야했습니다. 마지막에있는 방법 인 logAllEmitterEvents는 중요한 비트입니다.
var events = require('events');
var hungryAnimalEventEmitter = new events.EventEmitter();
function emitHungryAnimalEvents()
{
hungryAnimalEventEmitter.emit("HungryCat");
hungryAnimalEventEmitter.emit("HungryDog");
hungryAnimalEventEmitter.emit("Fed");
}
var meow = function meow()
{
console.log('meow meow meow');
}
hungryAnimalEventEmitter.on('HungryCat', meow);
logAllEmitterEvents(hungryAnimalEventEmitter);
emitHungryAnimalEvents();
function logAllEmitterEvents(eventEmitter)
{
var emitToLog = eventEmitter.emit;
eventEmitter.emit = function () {
var event = arguments[0];
console.log("event emitted: " + event);
emitToLog.apply(eventEmitter, arguments);
}
}
모든 라이브러리에서 생성 된 모든 이벤트를 추적해야했기 때문에 prototype
.
이 예제는를 사용 Typescript signature
하지만, 그런 종류의 말도 안되는 일이 아니라면 제거 할 수 있습니다.
호출 내에서 this
방출하는 객체를 나타냅니다. 내 프로젝트에서 모든 고유 한 객체를 추적하는 것은 매우 쉬웠습니다.
// For my example I use a `set` to track unique emits.
const items = new Set()
const originalEmit = EventEmitter.prototype.emit;
EventEmitter.prototype.emit = function (event: String | Symbol, ...args: any[]): boolean {
// Do what you want here
const id = this.constructor.name + ":" + event;
if (!items.has(id)) {
items.add(id);
console.log(id);
}
// And then call the original
return originalEmit.call(event, ...args);
}
이를 매우 쉽게 확장하고 이벤트 이름 또는 클래스 이름을 기반으로 필터링 할 수 있습니다.
node.js 용 RPC 모듈을 살펴볼 수 있습니다. 내가 착각하지 않는다면 Dnode RPC 모듈은 당신이하려는 것과 유사한 채팅 서버 / 클라이언트 예제 를 가지고 있습니다. 그래서 당신은 그들의 모듈을 사용하거나 그들이하는 일을 복사 할 수 있습니다.
간단히 말해서 예제는 연결시 연결된 클라이언트의 모든 서버 이벤트에 대한 리스너를 생성하는 서버를 보여줍니다. 저장된 이벤트 이름 목록을 간단히 반복하여이를 수행합니다.
var evNames = [ 'joined', 'said', 'parted' ];
con.on('ready', function () {
evNames.forEach(function (name) {
emitter.on(name, client[name]);
});
emitter.emit('joined', client.name);
});
이 코드는 이벤트가 발생할 때 이벤트와 관련된 클라이언트에서 원격 프로 시저 호출을 자동으로 호출하기 때문에 영리합니다.
오늘 같은 문제가 발생했습니다. 여기에 해결책이 있습니다.
Object.create(Object.assign({},EventEmitter.prototype, {
_onAnyListeners:[],
emit:function(...args){
//Emit event on every other server
if(this._fireOnAny && typeof this._fireOnAny === 'function'){
this._fireOnAny.apply(this,args)
}
EventEmitter.prototype.emit.apply(this,args)
},
_fireOnAny:function(...args){
this._onAnyListeners.forEach((listener)=>listener.apply(this,args))
},
onAny:function(func){
if(typeof func !== 'function'){
throw new Error('Invalid type');
}
this._onAnyListeners.push(func);
},
removeOnAny:function(func){
const index = this._onAnyListeners.indexOf(func);
if(index === -1){
return;
}
this._onAnyListeners.splice(index,1);
}
}));
Since Node.js v6.0.0, the new class
syntax and argument spread operator is fully supported, so it's pretty safe and fairly easy to implement the desired functionality with simple inheritance and an method override:
'use strict';
var EventEmitter = require('events');
class MyEmitter extends EventEmitter {
emit(type, ...args) {
super.emit('*', ...args);
return super.emit(type, ...args) || super.emit('', ...args);
}
}
This implementation relies on the fact that the original emit
method of the EventEmitter
returns true
/false
depending if the event was handled by some listener or not. Notice that the override includes a return
statement, so we keep this behavior for other consumers.
Here the idea is to use the star event (*
) to create handlers that gets executed on every single event (say, for logging purposes) and the empty event (''
) for a default or catch all handler, that gets executed if nothing else catches that event.
We make sure to call the star (*
) event first, because in case of error
events without any handlers, the result is actually an exception being thrown. For more details, take a look at the implementation of the EventEmitter
.
For example:
var emitter = new MyEmitter();
emitter.on('foo', () => console.log('foo event triggered'));
emitter.on('*', () => console.log('star event triggered'));
emitter.on('', () => console.log('catch all event triggered'));
emitter.emit('foo');
// Prints:
// star event triggered
// foo event triggered
emitter.emit('bar');
// Prints:
// star event triggered
// catch all event triggered
Finally, if an EventEmitter instance already exists but you want to adjust that specific instance to the new behavior, it can be easily done by patching the method at runtime like this:
emitter.emit = MyEmitter.prototype.emit;
a monkey patch add onAny method to EventEmitter.
it is useful to be able to monitor only events of one problem.
var EventEmitter=require('events')
var origemit=EventEmitter.prototype.emit;
Object.assign( EventEmitter.prototype, {
emit:function(){
if(this._onAnyListeners){
this._onAnyListeners.forEach((listener)=>listener.apply(this,arguments))
}
return origemit.apply(this,arguments)
},
onAny:function(func){
if(typeof func !== 'function'){
throw new Error('Invalid type');
}
if(!this._onAnyListeners)this._onAnyListeners=[];
this._onAnyListeners.push(func);
},
removeOnAny:function(func){
const index = this._onAnyListeners.indexOf(func);
if(index === -1){
return;
}
this._onAnyListeners.splice(index,1);
}
});
// usage example
//gzip.onAny(function(a){console.log(a)})
You can also use another event emitter implementation like https://github.com/ozantunca/DispatcherJS. The implementation would be like:
dispatcher.on('*', function () {});
DispatcherJS also supports namespaces and even dependencies to determine which callbacks are going to be called first.
Here's a debug tool inspired by Martin's answer (https://stackoverflow.com/a/18087021/1264797). I just now used this to figure out what was going wrong in a set of streams by logging all of their events to the console. Works great. As Martin illustrates, OP could use it by replacing the console.log() call with a websocket sender.
function debug_emitter(emitter, name) {
var orig_emit = emitter.emit;
emitter.emit = function() {
var emitArgs = arguments;
console.log("emitter " + name + " " + util.inspect(emitArgs));
orig_emit.apply(emitter, arguments);
}
}
참고URL : https://stackoverflow.com/questions/5178869/listen-to-all-emitted-events-in-node-js
'Program Tip' 카테고리의 다른 글
브라우저 간 방식으로 뷰포트의 정확한 높이와 너비를 찾습니다 (Prototype / jQuery 없음). (0) | 2020.11.17 |
---|---|
JQuery에서 도트 및 해시 기호는 무엇을 의미합니까? (0) | 2020.11.17 |
내 주요 기능이 반환 한 것을 어떻게 얻을 수 있습니까? (0) | 2020.11.17 |
VirtualBox에서 우분투 게스트를 핑하는 방법 (0) | 2020.11.17 |
숫자 선택기 대화 상자를 만드는 방법은 무엇입니까? (0) | 2020.11.17 |