2012-05-01 20 views
60

有沒有可能有一個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? 
}); 

我想這個回調函數,當任何/所有事情都是由客戶端收到的插座被調用。 io代碼。

這可能嗎?怎麼樣?

+0

我打開在轉發所有事件類型時遇到以下問題,我還添加了我找到的解決方案: https://github.com/Automattic/socket.io/issues/1715 –

回答

19

它看起來像socket.io庫將它們存儲在字典中。因此,如果不修改源代碼,不要以爲這是可能的。

source

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

也發現這個:http:// stackoverflow。com/questions/8832414/overriding-socket-ios-emit-and-on/8838225 –

10

在這裏你去...

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

這將捕獲的事件,如connectingconnectdisconnectreconnecting太多,所以要小心。

+0

Socket.IO.js build:0.9.10,development。 –

+3

這是否最終在發佈? – hacklikecrack

7

當前(2013年4月)GitHub doc on exposed events提到了socket.on('anything')。看起來,「任何事物」都是自定義事件名稱的佔位符,而不是可以捕捉任何事件的實際關鍵字。

我剛剛開始使用Web套接字和Node.JS,並立即需要處理任何事件,以及發現發送的事件。不能相信socket.io中缺少這個功能。

3

在Socket.IO存儲庫問題頁面上有a long discussion about this topic。在那裏發佈了各種解決方案(例如,用EventEmitter2覆蓋EventEmitter)。 lmjabreu幾個星期前發佈了另一個解決方案:一個名爲socket.io-wildcard的npm模塊,它將通配符事件補丁到Socket.IO(適用於當前的Socket.IO,〜0.9.14)。

+3

但這只是serverside ...他的模塊在客戶端(瀏覽器)上不可用 – Sander

9

注:這個答案是僅適用於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)); 
}); 
+0

在調用apply之前,有關aync操作的任何建議。 \t的setTimeout(函數(){ \t \t \t \t original_ $ emit.apply(插座,[ '*'] CONCAT(參數));! \t \t \t \t如果(original_ $ emit.apply(插座,參數) ){ \t \t \t \t \t original_ $ emit.apply)(插座,[ '缺省']的concat(參數); \t \t \t \t} \t \t \t},2000); – Enki

+0

我正在使用Socket.IO 1.3.6,並且''socket'中似乎沒有$ emit方法 – raimohanska

+0

確實。檢查@Flion的答案爲1.x版本 –

1

所有的方法,我發現(包括socket.io通配符和socketio通配符)我沒有工作。顯然在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)...

+0

我可以證實它的工作原理,正如你所觀察到的,它是唯一可行的(從某種意義上說:對我而言)。非常感謝你! – mark

3

因爲你的問題在尋求解決方案時相當普遍,我會介紹這個不需要破解代碼的問題,只需改變你的使用方式插座。

我只是決定讓我的客戶端應用程序發送完全相同的事件,但使用不同的有效載荷。

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

和服務器的東西像...

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

如果總是使用相同的事件可能導致的任何問題,也許某種大規模的衝突,我不知道,但是這服務我的目的就好了。

1

@Matthias Hopf回答

更新後的答案爲v1.3.5。如果你想一起聽舊的事件和事件,那麼有一個參數錯誤。

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

爲socket.io客戶端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

+2

這工作完美 - 謝謝! – Jonathan

+1

不幸的是,沒有使用'user。*'之類的東西。也許我可以設法實現它。 – C4u

12

最後,有一個叫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); 
+0

完美運作 – tinybyte

2

通配符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) 
    } 
}) 

參考文獻:

相關問題