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 код.
это возможно? Как?
12 ответов:
похоже, что 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-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);
вы идете ...
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
можно переопределить гнездо.$излучают
С помощью следующего кода у вас есть две новые функции:
- ловушка все события
- ловушка только события, которые не захвачены старым методом (это слушатель по умолчанию)
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)GitHub doc о выставленных событиях упоминает a
socket.on('anything')
. Похоже, что "что-либо" является заполнителем для пользовательского имени события, а не фактическим ключевым словом, которое будет ловить любое событие.Я только начал работать с веб-сокетами и узлов.JS, и сразу же возникла необходимость обработать любое событие, а также выяснить, какие события были отправлены. Не могу поверить, что эта функциональность отсутствует socket.io.
socket. io-client 1.7.3
по состоянию на май 2017 года не смог заставить ни одно из других решений работать так, как я хотел - сделал перехватчик, используя at 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 страница выпуска репозитория. Существует множество решений, размещенных там (например, переопределение EventEmitter с EventEmitter2). lmjabreu выпустила еще одно решение пару недель назад: модуль npm под названием socket. io-wildcard, который исправляет событие wildcard на Socket.IO (работает с текущим 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), не работали для меня. По-видимому, нет $emit in socket.io 1.3.5...
после прочтения socket.io код, я исправил следующее, что действительно работало:
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 answer
обновленный ответ для 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 и пакет npm:фабриката необходмо предусмотреть розетку-Ио
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}]`); } });