source

Node.js에서 발신된 모든 이벤트 듣기

itover 2023. 4. 2. 10:21
반응형

Node.js에서 발신된 모든 이벤트 듣기

Node.js에서는 EventEmitter 객체에 의해 발신된 모든 이벤트를 리슨하는 방법이 있습니까?

예를 들어, 다음과 같은 것을 할 수 있습니까?

event_emitter.on('',function(event[, arg1][, arg2]...) {}

를 모두 입니다.EventEmitter,JSON.stringify이벤트 데이터를 웹소켓 연결을 통해 전송하고 클라이언트 측에서 이벤트로 재구성한 다음 클라이언트 측에서 이벤트를 처리합니다.

이게 좀 오래된 건 알지만, 대체, 여기 당신이 취할 수 있는 다른 해결책이 있어요.

모든 이벤트를 포착하는 이미터의 이미트 함수를 쉽게 원숭이로 패치할 수 있습니다.

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);
  }
}

이것은 매우 간단한 코드이며, 모든 이미터에서 동작합니다.

전술한 바와 같이 이 동작은 node.js core에는 없습니다.그러나 hij1nx의 EventEmitter2를 사용할 수 있습니다.

https://github.com/hij1nx/EventEmitter2

EventEmitter를 사용하여 기존 코드를 해제하지 않지만 네임스페이스와 와일드카드 지원이 추가됩니다.예를 들어 다음과 같습니다.

server.on('foo.*', function(value1, value2) {
  console.log(this.event, value1, value2);
});

ES6 클래스에서는 매우 간단합니다.

class Emitter extends require('events') {
    emit(type, ...args) {
        console.log(type + " 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('*', ()=>...)디폴트로는 동작할 수 없습니다.

Node.js v6.0.0 입니다.class구문 및 인수 확산 연산자가 완전히 지원되므로 간단한 상속과 메서드 덮어쓰기를 통해 원하는 기능을 구현하는 것이 매우 안전하고 쉽습니다.

'use strict';
var EventEmitter = require('events');

class MyEmitter extends EventEmitter {
  emit(type, ...args) {
    super.emit('*', ...args);
    return super.emit(type, ...args) || super.emit('', ...args);
  }
}

에서는, 의 「」, 「PC」, 「PC」, 「PC」가, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「PC」, 「」, 「」,emit의 of의 EventEmittertrue/false이벤트가 일부 청취자에 의해 처리되었는지 여부에 따라 달라집니다.에는 「」가 포함되어 있는 것에 해 주세요.return다른 소비자를 위해 이 동작을 유지합니다.

서는 별자리 이벤트 이벤트)를 입니다.*를 들어 로깅을 및빈예를 들어, " " " ( " " " " ( " " " " " " ) " 을 합니다.''디폴트 핸들러 또는 catch all 핸들러의 경우 해당 이벤트가 검출되지 않으면 실행됩니다.

.*하도록 하겠습니다.왜냐하면error핸들러가 없는 이벤트에서는 실제로는 예외가 느려집니다.상세한 것에 대하여는, 의 실장을 참조해 주세요.

예를 들어 다음과 같습니다.

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

마지막으로 EventEmitter 인스턴스가 이미 존재하지만 특정 인스턴스를 새로운 동작에 맞게 조정하려면 다음과 같이 실행 시 메서드에 패치를 적용하면 됩니다.

emitter.emit = MyEmitter.prototype.emit;

이것은 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);
    }
}

라이브러리에서 한 모든 에 "Manager"를 .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);
  }

이벤트 이름 또는 클래스 이름을 기준으로 필터링 및 확장을 매우 쉽게 수행할 수 있습니다.

monkey patch add on Event Emitter에 임의의 메서드를 추가합니다.

한 가지 문제의 이벤트만 감시할 수 있으면 편리합니다.

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)})

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);
  }
}));

다음은 Martin의 답변에서 영감을 얻은 디버깅 도구입니다(https://stackoverflow.com/a/18087021/1264797)).이 기능을 사용하여 스트림의 모든 이벤트를 콘솔에 기록함으로써 스트림 집합에서 무엇이 잘못되었는지 알아냈습니다.효과가 좋다.Martin이 설명한 바와 같이 OP는 console.log() 콜을 웹 소켓 송신기로 대체하여 사용할 수 있습니다.

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);
    }
}

https://github.com/ozantunca/DispatcherJS 등의 다른 이벤트 이미터 구현도 사용할 수 있습니다.실장은 다음과 같습니다.

dispatcher.on('*', function () {});

디스패처또한 JS는 네임스페이스 및 의존관계도 지원하여 어떤 콜백을 먼저 호출할지를 결정합니다.

언급URL : https://stackoverflow.com/questions/5178869/listen-to-all-emitted-events-in-node-js

반응형