Socket.io Client: phản hồi tất cả các sự kiện bằng một trình xử lý?


82

Có thể có ứng dụng khách socket.io phản hồi tất cả các sự kiện mà không cần chỉ định từng sự kiện riêng lẻ không?

Ví dụ: một cái gì đó như thế này (rõ ràng là không hoạt động ngay bây giờ):

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

Tôi muốn hàm gọi lại này được gọi khi bất kỳ / tất cả các sự kiện được nhận bởi mã socket.io phía máy khách.

Điều này có khả thi không? Làm sao?


Tôi mở vấn đề sau đây về chuyển tiếp tất cả các loại sự kiện, tôi cũng đã được bổ sung thêm các giải pháp tôi thấy: github.com/Automattic/socket.io/issues/1715
Peter Uithoven

Câu trả lời:


25

Có vẻ như thư viện socket.io lưu trữ chúng trong một từ điển. Do đó, đừng nghĩ rằng điều này sẽ khả thi nếu không sửa đổi nguồn.

Từ nguồn :

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
cũng tìm thấy điều này: stackoverflow.com/questions/8832414/…
Derick Bailey

Vào năm 2019, tôi không nghĩ là trường hợp này nữa.
Urasquirrel

82

Giải pháp cập nhật cho 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
};

Sử dụng như thế này:

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

Không có câu trả lời nào phù hợp với tôi, mặc dù một trong số Mathias Hopf và Maros Pixel đã gần kề, đây là phiên bản điều chỉnh của tôi.

LƯU Ý: điều này chỉ bắt các sự kiện tùy chỉnh, không kết nối / ngắt kết nối, v.v.


2
Cảm ơn bạn, điều này đã giúp tôi gỡ lỗi các sự kiện bị thiếu!
Maitreya

1
Rất tiếc là không hoạt động với những thứ như 'user. *' ;. Có lẽ tôi có thể quản lý để thực hiện nó.
C4d

Hi, rất tốt, nhưng nó có thể hữu ích nếu bạn có thể có một số ví dụ đầu ra ^^ Tôi cảm thấy như tôi cần phải chạy mã để hiểu câu trả lời của bạn :)
538ROMEO

24

Cuối cùng , có một mô-đun được gọi là socket.io-wildcard cho phép sử dụng các ký tự đại diện ở phía máy khách và máy chủ

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

Của bạn đây ...

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

Điều này sẽ bắt các sự kiện như connecting, connect, disconnect, reconnectingquá, vì vậy làm nâng niu mang.


Socket.IO.js xây dựng: 0.9.10, phát triển.
Kaustubh Karkare 14/10/12

3
Điều này đã kết thúc trong một bản phát hành?
hacklikecrack

9

Lưu ý: câu trả lời này chỉ hợp lệ cho socket.io 0.x

Bạn có thể ghi đè socket. $ Nhũ

Với đoạn mã sau, bạn có hai chức năng mới để:

  • Bẫy tất cả các sự kiện
  • Chỉ bẫy các sự kiện không bị mắc kẹt bởi phương pháp cũ (nó là trình nghe mặc định)
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));
});

Mọi lời khuyên về thao tác aync trước khi gọi đều được áp dụng. setTimeout (function () {original_ $ release.apply (socket, ['*']. concat (args)); if (! original_ $ release.apply (socket, đối số)) {original_ $ release.apply (socket, [ 'default']. concat (args));}}, 2000);
Enki

Tôi đang sử dụng Socket.IO 1.3.6 và có vẻ không phải là một phương pháp Emit $ trong socketnữa
raimohanska

Thật. Kiểm tra @Flion câu trả lời cho 1.x phiên bản
leszek.hanusz

7

Tài liệu GitHub hiện tại (tháng 4 năm 2013) về các sự kiện tiếp xúc đề cập đến a socket.on('anything'). Có vẻ như 'bất kỳ thứ gì' là trình giữ chỗ cho tên sự kiện tùy chỉnh, không phải là từ khóa thực tế sẽ bắt bất kỳ sự kiện nào.

Tôi vừa mới bắt đầu làm việc với web socket và Node.JS, và ngay lập tức có nhu cầu xử lý bất kỳ sự kiện nào, cũng như khám phá những sự kiện nào đã được gửi đi. Không thể tin rằng chức năng này bị thiếu trong socket.io.


5

socket.io-client 1.7.3

Kể từ tháng 5 năm 2017, không thể làm cho bất kỳ giải pháp nào khác hoạt động theo cách tôi muốn - đã tạo một bộ đánh chặn, sử dụng tại Node.js chỉ cho mục đích thử nghiệm:

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

Người giới thiệu:


3

một cuộc thảo luận dài về chủ đề này đang diễn ra tại trang vấn đề kho Socket.IO. Có nhiều giải pháp được đăng ở đó (ví dụ: ghi đè EventEmitter bằng EventEmitter2). lmjabreu đã phát hành một giải pháp khác cách đây vài tuần: một mô-đun npm có tên là socket.io-wildcard vá lỗi trong một sự kiện ký tự đại diện trên Socket.IO (hoạt động với Socket.IO hiện tại, ~ 0.9.14).


4
Nhưng đó chỉ là serverside ... mô-đun của ông là không thể sử dụng trên clientside (trình duyệt)
Sander

3

Bởi vì câu hỏi của bạn khá chung chung trong việc yêu cầu giải pháp, tôi sẽ đưa ra câu hỏi này không yêu cầu hack mã, chỉ là một sự thay đổi trong cách bạn sử dụng socket.

Tôi vừa quyết định để ứng dụng khách hàng của mình gửi cùng một sự kiện, nhưng với tải trọng khác.

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

Và trên máy chủ, một cái gì đó giống như ...

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

Tôi không biết liệu việc luôn sử dụng cùng một sự kiện có thể gây ra bất kỳ vấn đề nào không, có thể là va chạm ở quy mô nào đó, nhưng điều này phục vụ mục đích của tôi rất tốt.


1

Tất cả các phương pháp tôi tìm thấy (bao gồm cả socket.io-wildcard và socketio-wildcard) không hoạt động với tôi. Rõ ràng là không có $ phát ra trong socket.io 1.3.5 ...

Sau khi đọc mã socket.io, tôi đã vá các lỗi sau mà DID hoạt động:

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

Đây cũng có thể là một giải pháp cho những người khác. Tuy nhiên, ATM tôi không hiểu chính xác tại sao dường như không ai khác có vấn đề với các "giải pháp" hiện có?!? Có ý kiến ​​gì không? Có thể đó là phiên bản nút cũ của tôi (0.10.31) ...


Tôi có thể xác nhận nó hoạt động và, như bạn đã quan sát, là cái duy nhất hoạt động (theo nghĩa: đối với tôi cũng vậy). Cảm ơn rât nhiều!
đánh dấu

1

@Matthias Hopf câu trả lời

Cập nhật câu trả lời cho v1.3.5. Đã xảy ra lỗi với args, nếu bạn muốn nghe sự kiện cũ và *sự kiện cùng nhau.

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

Mặc dù đây là một câu hỏi cũ, tôi có cùng một vấn đề và đã giải quyết bằng cách sử dụng socket gốc trong Node.js, có sự kiện .on ('data'), được kích hoạt mỗi khi có một số dữ liệu. Vì vậy, đây là những gì tôi đã làm cho đến nay:

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

Tôi đang sử dụng Angular 6 và gói npm : ngx-socket-io

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

...

constructor(private socket: Socket) { }

...

Sau khi kết nối ổ cắm, tôi sử dụng mã này, điều này đang xử lý tất cả các sự kiện tùy chỉnh ...

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}]`);
  }
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.