Socket.io 클라이언트 : 하나의 핸들러로 모든 이벤트에 응답합니까?


82

socket.io 클라이언트가 각 이벤트를 개별적으로 지정하지 않고도 모든 이벤트에 응답하도록 할 수 있습니까?

예를 들어, 다음과 같은 것 (지금 당장은 분명히 작동하지 않음) :

var socket = io.connect("http://myserver");

socket.on("*", function(){
  // listen to any and all events that are emitted from the
  // socket.io back-end server, and handle them here.

  // is this possible? how can i do this?
});

클라이언트 측 socket.io 코드에서 모든 이벤트를 수신 할 때이 콜백 함수가 호출되기를 원합니다.

이것이 가능한가? 어떻게?


모든 이벤트 유형 전달에 대한 다음 문제를 열었고 찾은 솔루션도 추가했습니다. github.com/Automattic/socket.io/issues/1715
Peter Uithoven

답변:


25

socket.io 라이브러리가 사전에 저장하는 것처럼 보입니다. 따라서 소스를 수정하지 않고는 이것이 가능할 것이라고 생각하지 마십시오.

에서 소스 :

EventEmitter.prototype.on = function (name, fn) {
    if (!this.$events) {
      this.$events = {};
    }

    if (!this.$events[name]) {
      this.$events[name] = fn;
    } else if (io.util.isArray(this.$events[name])) {
      this.$events[name].push(fn);
    } else {
      this.$events[name] = [this.$events[name], fn];
    }

    return this;
  };

3
또한 이것을 발견했습니다 : stackoverflow.com/questions/8832414/…
Derick Bailey

2019 년에는 더 이상 그렇지 않다고 생각합니다.
Urasquirrel

82

socket.io-client 1.3.7에 대한 업데이트 된 솔루션

var onevent = socket.onevent;
socket.onevent = function (packet) {
    var args = packet.data || [];
    onevent.call (this, packet);    // original call
    packet.data = ["*"].concat(args);
    onevent.call(this, packet);      // additional call to catch-all
};

다음과 같이 사용하십시오.

socket.on("*",function(event,data) {
    console.log(event);
    console.log(data);
});

Mathias Hopf와 Maros Pixel 중 하나가 가까워졌지만 이것은 내가 조정 한 버전입니다.

참고 : 이것은 연결 / 연결 해제 등이 아닌 사용자 지정 이벤트 만 포착합니다.


2
감사합니다. 이것은 누락 된 이벤트를 디버그하는 데 도움이되었습니다!
Maitreya

1
불행히도 'user. *';와 같은 작업을하지 않습니다. 아마도 내가 그것을 구현할 수있을 것입니다.
C4d

안녕하세요, 아주 좋습니다.하지만 출력 예제가 있으면 도움이 될 수 있습니다 ^^ 답변을 이해하기 위해 코드를 실행해야 할 것 같습니다. :)
538ROMEO

24

마지막으로 클라이언트와 서버 측에서 와일드 카드 를 사용할 수있는 socket.io-wildcard 라는 모듈 이 있습니다.

var io         = require('socket.io')();
var middleware = require('socketio-wildcard')();

io.use(middleware);

io.on('connection', function(socket) {
  socket.on('*', function(){ /* … */ });
});

io.listen(8000);

11

여기 있습니다 ...

var socket = io.connect();
var globalEvent = "*";
socket.$emit = function (name) {
    if(!this.$events) return false;
    for(var i=0;i<2;++i){
        if(i==0 && name==globalEvent) continue;
        var args = Array.prototype.slice.call(arguments, 1-i);
        var handler = this.$events[i==0?name:globalEvent];
        if(!handler) handler = [];
        if ('function' == typeof handler) handler.apply(this, args);
        else if (io.util.isArray(handler)) {
            var listeners = handler.slice();
            for (var i=0, l=listeners.length; i<l; i++)
                listeners[i].apply(this, args);
        } else return false;
    }
    return true;
};
socket.on(globalEvent,function(event){
    var args = Array.prototype.slice.call(arguments, 1);
    console.log("Global Event = "+event+"; Arguments = "+JSON.stringify(args));
});

이 같은 행사 잡을 것 connecting, connect, disconnect, reconnecting너무, 너무 돌봐를 수행하십시오.


Socket.IO.js 빌드 : 0.9.10, 개발.
Kaustubh Karkare

3
이것이 릴리스로 끝났습니까?
hacklikecrack

9

참고 :이 답변은 socket.io 0.x에만 유효합니다.

socket. $ emit을 재정의 할 수 있습니다 .

다음 코드를 사용하면 두 가지 새로운 기능이 있습니다.

  • 모든 이벤트 트랩
  • 이전 메서드에 의해 트랩되지 않은 이벤트 만 트랩 (기본 리스너)
var original_$emit = socket.$emit;
socket.$emit = function() {
    var args = Array.prototype.slice.call(arguments);
    original_$emit.apply(socket, ['*'].concat(args));
    if(!original_$emit.apply(socket, arguments)) {
        original_$emit.apply(socket, ['default'].concat(args));
    }
}

socket.on('default',function(event, data) {
    console.log('Event not trapped: ' + event + ' - data:' + JSON.stringify(data));
});

socket.on('*',function(event, data) {
    console.log('Event received: ' + event + ' - data:' + JSON.stringify(data));
});

전화하기 전에 aync 작업에 대한 모든 조언이 적용됩니다. setTimeout (function () {original_ $ emit.apply (socket, [ '*']. concat (args)); if (! original_ $ emit.apply (socket, arguments)) {original_ $ emit.apply (socket, [ 'default']. concat (args));}}, 2000);
Enki

내가 Socket.IO 1.3.6을 사용하고 있는데 달러 (A $)의 발광 방법이있을 것 같지 않습니다 socket더 이상은
raimohanska

과연. 1.x의 버전 @Flion 답변을 확인
leszek.hanusz

7

노출 된 이벤트에 대한 현재 (2013 년 4 월) GitHub 문서 에는 socket.on('anything'). 'anything'은 이벤트를 포착하는 실제 키워드가 아니라 사용자 지정 이벤트 이름에 대한 자리 표시자인 것으로 보입니다.

방금 웹 소켓과 Node.JS로 작업을 시작했고 즉시 이벤트를 처리하고 어떤 이벤트가 전송되었는지 알아 내야했습니다. 이 기능이 socket.io에 없다는 것을 믿을 수 없습니다.


5

socket.io-client 1.7.3

2017 년 5 월 현재 다른 솔루션이 내가 원하는대로 작동하도록 만들 수 없었습니다. 테스트 목적으로 만 Node.js를 사용하여 인터셉터를 만들었습니다.

var socket1 = require('socket.io-client')(socketUrl)
socket1.on('connect', function () {
  console.log('socket1 did connect!')
  var oldOnevent = socket1.onevent
  socket1.onevent = function (packet) {
    if (packet.data) {
      console.log('>>>', {name: packet.data[0], payload: packet.data[1]})
    }
    oldOnevent.apply(socket1, arguments)
  }
})

참조 :


3

이 주제에 대한 긴 토론 Socket.IO 저장소 문제 페이지에서 진행은. 거기에 게시 된 다양한 솔루션이 있습니다 (예 : EventEmitter2로 EventEmitter 재정의). lmjabreu는 몇 주 전에 또 다른 솔루션을 출시 했습니다. 와일드 카드 이벤트를 Socket.IO에 패치하는 socket.io-wildcard 라는 npm 모듈 (현재 Socket.IO, ~ 0.9.14에서 작동)입니다.


4
그러나 그것은 (브라우저) 자신의 모듈은 클라이언트 측에서 사용할 수 없습니다 ... 단지 서버 쪽입니다
샌더

3

귀하의 질문은 해결책을 요청하는 데 매우 일반적 이었기 때문에 코드를 해킹하지 않고 소켓을 사용하는 방법 만 변경하면이 질문을 던질 것입니다.

내 클라이언트 앱이 정확히 동일한 이벤트를 보내도록 결정했지만 페이로드는 다릅니다.

socket.emit("ev", { "name" : "miscEvent1"} );
socket.emit("ev", { "name" : "miscEvent2"} );

그리고 서버에서 ...

socket.on("ev", function(eventPayload) {
   myGenericHandler(eventPayload.name);
});

항상 동일한 이벤트를 사용하는 것이 문제를 일으킬 수 있는지, 어쩌면 어떤 종류의 충돌이 대규모로 발생할 수 있는지는 모르겠지만 이것은 내 목적에 잘 맞았습니다.


1

내가 찾은 모든 방법 (socket.io-wildcard 및 socketio-wildcard 포함)이 저에게 작동하지 않았습니다. 분명히 socket.io 1.3.5에는 $ emit이 없습니다 ...

socket.io 코드를 읽은 후 DID가 작동하는 다음을 패치했습니다.

var Emitter = require('events').EventEmitter;
var emit = Emitter.prototype.emit;
[...]
var onevent = socket.onevent;
socket.onevent = function (packet) {
    var args = ["*"].concat (packet.data || []);
    onevent.call (this, packet);    // original call
    emit.apply   (this, args);      // additional call to catch-all
};

이것은 다른 사람들에게도 해결책이 될 수 있습니다. 그러나 ATM 나는 왜 다른 사람들이 기존의 "솔루션"에 문제가없는 것처럼 보이는지 정확히 이해하지 못한다?!? 어떤 아이디어? 아마도 내 이전 노드 버전 (0.10.31) 일 수 있습니다.


나는 그것이 효과가 있음을 확인할 수 있으며, 당신이 관찰 한 바와 같이, 작동하는 유일한 사람입니다. 대단히 감사합니다!
마크

1

@Matthias Hopf 대답

v1.3.5에 대한 답변이 업데이트되었습니다. 이전 이벤트와 *이벤트를 함께 듣고 싶다면 args에 버그가 있습니다.

var Emitter = require('events').EventEmitter;
var emit = Emitter.prototype.emit;
// [...]
var onevent = socket.onevent;
socket.onevent = function (packet) {
    var args = packet.data || [];
    onevent.call (this, packet);    // original call
    emit.apply   (this, ["*"].concat(args));      // additional call to catch-all
};

1

이것은 오래된 질문이지만 동일한 문제 Node.js가 있으며 .on ( 'data') 이벤트가있는 네이티브 소켓을 사용하여 일부 데이터가 올 때마다 발생합니다. 그래서 이것은 내가 지금까지 한 일입니다.

const net = require('net')

const server = net.createServer((socket) => {
    // 'connection' listener.
    console.log('client connected')

    // The stuff I was looking for
    socket.on('data', (data) => {
        console.log(data.toString())
    })

    socket.on('end', () => {
        console.log('client disconnected')
    })
})

server.on('error', (err) => {
    throw err;
})

server.listen(8124, () => {
    console.log('server bound');
})

0

내가 사용하고 6 각도 와 고궁 박물원 패키지 : NGX-소켓 IO를

import { Socket } from "ngx-socket-io";

...

constructor(private socket: Socket) { }

...

소켓을 연결 한 후이 코드를 사용하면 모든 사용자 지정 이벤트를 처리합니다.

const onevent = this.socket.ioSocket.onevent;
this.socket.ioSocket.onevent = function (packet: any) {
  const args = packet.data || [];
  onevent.call(this, packet);    // original call
  packet.data = ["*"].concat(args);
  onevent.call(this, packet);      // additional call to catch-all
};
this.socket.on("*", (eventName: string, data: any) => {
  if (typeof data === 'object') {
    console.log(`socket.io event: [${eventName}] -> data: [${JSON.stringify(data)}]`);
  } else {
    console.log(`socket.io event: [${eventName}] -> data: [${data}]`);
  }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.