ProgramingTip

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

bestdevel 2020. 10. 16. 07:44
반응형

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


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 코드에서 이벤트를 수신 할 때이 함수가 호출되기를 원합니다.

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


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

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 중 하나가 가까워졌지만이 내 조정 버전입니다.

참고 :이 연결 / 연결 해제 등이 아닌 사용자 지정 이벤트가 발생합니다.


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

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

io.use(middleware);

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

io.listen(8000);

여기 있습니다 ...

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 0.x에만 유효합니다.

소켓. $ 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));
});

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

방금 웹 소켓 및 Node.JS 작업을 시작했으며 즉시 이벤트를 처리하고 전송 된 이벤트를 발견해야했습니다. 이 기능이 socket.io에 없다는 것을 믿을 수 없습니다.


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

참조 :


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


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

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

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

그리고 서버에서 ...

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

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


내가 찾은 모든 방법 (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) 일 수 있습니다.


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

내가 사용하고 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}]`);
  }
});

참고 URL : https://stackoverflow.com/questions/10405070/socket-io-client-respond-to-all-events-with-one-handler

반응형