Socket.io Client: tüm olaylara tek bir işleyiciyle yanıt verilsin mi?


83

Her olayı ayrı ayrı belirtmeden bir socket.io istemcisinin tüm olaylara yanıt vermesi mümkün müdür?

Örneğin, bunun gibi bir şey (şu anda açıkçası çalışmıyor):

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

İstemci tarafı socket.io kodu tarafından herhangi bir / tüm olay alındığında bu geri arama işlevinin çağrılmasını istiyorum.

Mümkün mü? Nasıl?


Tüm olay türlerini iletmekle
Peter Uithoven

Yanıtlar:


25

Görünüşe göre socket.io kitaplığı bunları bir sözlükte saklıyor. Bu nedenle, kaynağı değiştirmeden bunun mümkün olacağını düşünmeyin.

Gönderen kaynağı :

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


2019'da artık durumun böyle olduğunu düşünmüyorum.
Urasquirrel

82

Socket.io-client 1.3.7 için güncellenmiş çözüm

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

Bunun gibi kullanın:

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

Mathias Hopf ve Maros Pixel'den biri yaklaşsa da, yanıtların hiçbiri benim için işe yaramadı, bu benim ayarlanmış sürümüm.

NOT: bu yalnızca özel olayları yakalar, bağlanma / bağlantıyı kesme vb.


2
Teşekkürler, bu eksik olayları ayıklamama yardımcı oldu!
Maitreya

1
Maalesef 'user. *'; Gibi şeylerle çalışmıyor. Belki uygulamayı başarabilirim.
C4d

Merhaba, çok güzel, ancak bazı çıktı örnekleriniz varsa faydalı olabilir ^^ Cevabınızı anlamak için kodu çalıştırmam gerektiğini düşünüyorum :)
grobouDu06

24

Son olarak , istemci ve sunucu tarafında joker karakterlerin kullanılmasına izin veren socket.io-wildcard adında bir modül var.

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

Hadi bakalım ...

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

Bu gibi olaylar yakalayacak connecting, connect, disconnect, reconnectingçok, bu yüzden icabına yapmak.


Socket.IO.js derlemesi: 0.9.10, geliştirme.
Kaustubh Karkare

3
Bu bir sürümle mi sonuçlandı?
hacklikecrack

9

Not: bu cevap yalnızca socket.io 0.x için geçerlidir.

Soketi geçersiz kılabilirsiniz . $ Emit

Aşağıdaki kodla iki yeni işleve sahipsiniz:

  • Tüm olayları tuzağa düşür
  • Yalnızca eski yöntem tarafından yakalanmayan olayları yakala (varsayılan bir dinleyicidir)
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));
});

Aramadan önce aync işlemi ile ilgili herhangi bir tavsiye geçerlidir. setTimeout (function () {orijinal_ $ emit.apply (soket, ['*']. concat (bağımsız değişkenler)); if (! orijinal_ $ emit.apply (soket, bağımsız değişkenler)) {orijinal_ $ emit.apply (soket, [ 'varsayılan']. concat (değiştirgeler));}}, 2000);
Enki

Socket.IO 1.3.6 kullanıyorum ve socketartık bir $ emit yöntemi görünmüyor
raimohanska

Aslında. 1.x sürümleri için @Flion cevabı kontrol
leszek.hanusz

7

Maruz kalan olaylarla ilgili mevcut (Nisan 2013) GitHub belgesinde a socket.on('anything'). Görünüşe göre 'herhangi bir şey', herhangi bir olayı yakalayacak gerçek bir anahtar kelime değil, özel bir etkinlik adı için yer tutucudur.

Web soketleri ve Node.JS ile çalışmaya yeni başladım ve hemen herhangi bir olayı ele almam ve hangi olayların gönderildiğini keşfetmem gerekiyordu. Bu işlevselliğin socket.io'da eksik olduğuna inanamıyorum.


5

socket.io-istemci 1.7.3

Mayıs 2017 itibarıyla, diğer çözümlerden hiçbirinin istediğim gibi çalışmasını sağlayamadı - yalnızca test amacıyla Node.js'de kullanarak bir durdurucu yaptı:

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

Referanslar:


3

Orada bu konu hakkında uzun bir tartışma Socket.IO deposu sorun sayfasındaki oluyor. Orada yayınlanan çeşitli çözümler vardır (örneğin, EventEmiter'ı EventEmitter2 ile geçersiz kılmak). lmjabreu birkaç hafta önce başka bir çözüm yayınladı: Socket.IO'ya bir joker karakter olayını ekleyen socket.io-wildcard adlı bir npm modülü (mevcut Socket.IO ile çalışır, ~ 0.9.14).


4
Ancak bu sadece sunucu tarafı ... modülü istemci tarafında (tarayıcı) kullanılamaz
Sander

3

Sorunuz bir çözüm istemede oldukça genel olduğu için, kodu kırmak gerekmeyen, sadece soketi kullanma şeklinizde bir değişiklik gerektirecek bir soru soracağım.

Sadece istemci uygulamamın aynı olayı farklı bir yük ile göndermesine karar verdim.

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

Ve sunucuda, şöyle bir şey ...

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

Her zaman aynı olayı kullanmanın herhangi bir soruna, belki büyük ölçekte bir tür çarpışmaya yol açıp açmayacağını bilmiyorum, ama bu, amacıma gayet iyi hizmet etti.


2

Bu eski bir soru olsa da, aynı sorunu yaşıyorum ve Node.jsher veri geldiğinde ateşlenen .on ('veri') olayı olan yerel soketi kullanarak çözdüm. İşte şimdiye kadar yaptığım şey bu:

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

1

Bulduğum tüm yöntemler (socket.io-wildcard ve socketio-wildcard dahil) benim için işe yaramadı. Görünüşe göre socket.io 1.3.5'te $ emit yok ...

Socket.io kodunu okuduktan sonra, DID'nin çalıştığı aşağıdakileri düzelttim:

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

Bu başkaları için de bir çözüm olabilir. Ancak, ATM Neden başka hiç kimsenin mevcut "çözümler" ile sorunları olmadığını tam olarak anlamıyorum?!? Herhangi bir fikir? Belki de eski düğüm sürümümdür (0.10.31) ...


Çalıştığını doğrulayabilirim ve sizin de gözlemlediğiniz gibi, işe yarayan tek kişi (bu anlamda: benim için de) Çok teşekkür ederim!
mark

1

@Matthias Hopf cevap

V1.3.5 için güncellenmiş yanıt. Eski olayı ve *olayı birlikte dinlemek isterseniz, args ile ilgili bir hata vardı.

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

0

Ben kullanıyorum 6 Açısal ve npm paketi: NGX-soket io

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

...

constructor(private socket: Socket) { }

...

Soketi bağladıktan sonra, bu kodu kullanıyorum, bu tüm özel olayları işliyor ...

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.