From 8fc1537275ae9dd22a3c9d670f2d5cf3212ef760 Mon Sep 17 00:00:00 2001 From: Ruben Rodriguez II Date: Sun, 25 Jan 2015 17:18:41 -0600 Subject: [PATCH] Suggestion for implementation of clients API --- Readme.md | 34 ++++++++++++++ lib/index.js | 2 +- lib/namespace.js | 12 +++++ test/socket.io.js | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index a30e681f66..6f8b473b31 100644 --- a/Readme.md +++ b/Readme.md @@ -240,6 +240,40 @@ server.listen(3000); Hash of `Socket` objects that are connected to this namespace indexed by `id`. +### Namespace#clients(fn:Function) + + Gets a list of client IDs connected to this namespace (across all nodes if applicable). + + An example to get all clients in a namespace: + + ```js + var io = require('socket.io')(); + io.of('/chat').clients(function(error, clients){ + if (error) throw error; + console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD] + }); + ``` + + An example to get all clients in namespace's room: + + ```js + var io = require('socket.io')(); + io.of('/chat').in('general').clients(function(error, clients){ + if (error) throw error; + console.log(clients); // => [Anw2LatarvGVVXEIAAAD] + }); + ``` + + As with broadcasting, the default is all clients from the default namespace ('/'): + + ```js + var io = require('socket.io')(); + io.clients(function(error, clients){ + if (error) throw error; + console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB] + }); + ``` + ### Namespace#use(fn:Function):Namespace Registers a middleware, which is a function that gets executed for diff --git a/lib/index.js b/lib/index.js index 03a87cfac1..c14c7ac4e1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -361,7 +361,7 @@ Server.prototype.close = function(){ * Expose main namespace (/). */ -['on', 'to', 'in', 'use', 'emit', 'send', 'write'].forEach(function(fn){ +['on', 'to', 'in', 'use', 'emit', 'send', 'write', 'clients'].forEach(function(fn){ Server.prototype[fn] = function(){ var nsp = this.sockets[fn]; return nsp.apply(this.sockets, arguments); diff --git a/lib/namespace.js b/lib/namespace.js index bee208c8ac..36cc941236 100644 --- a/lib/namespace.js +++ b/lib/namespace.js @@ -240,3 +240,15 @@ Namespace.prototype.write = function(){ this.emit.apply(this, args); return this; }; + +/** + * Gets a list of clients. + * + * @return {Namespace} self + * @api public + */ + +Namespace.prototype.clients = function(fn){ + this.adapter.clients(this.rooms, fn); + return this; +}; diff --git a/test/socket.io.js b/test/socket.io.js index 66103db62c..a175ac73d5 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -597,6 +597,122 @@ describe('socket.io', function(){ }); }); }); + + it('should find all clients in a namespace', function(done){ + var srv = http(); + var sio = io(srv); + var chatSids = []; + var otherSid = null; + srv.listen(function(){ + var c1 = client(srv, '/chat'); + var c2 = client(srv, '/chat', {forceNew: true}); + var c3 = client(srv, '/other', {forceNew: true}); + var total = 3; + sio.of('/chat').on('connection', function(socket){ + chatSids.push(socket.id); + --total || getClients(); + }); + sio.of('/other').on('connection', function(socket){ + otherSid = socket.id; + --total || getClients(); + }); + }); + function getClients() { + sio.of('/chat').clients(function(error, sids) { + expect(error).to.be.undefined; + expect(sids).to.contain(chatSids[0]); + expect(sids).to.contain(chatSids[1]); + expect(sids).to.not.contain(otherSid); + done(); + }); + } + }); + + it('should find all clients in a namespace room', function(done){ + var srv = http(); + var sio = io(srv); + var chatFooSid = null; + var chatBarSid = null; + var otherSid = null; + srv.listen(function(){ + var c1 = client(srv, '/chat'); + var c2 = client(srv, '/chat', {forceNew: true}); + var c3 = client(srv, '/other', {forceNew: true}); + var chatIndex = 0; + var total = 3; + sio.of('/chat').on('connection', function(socket){ + if (chatIndex++) { + socket.join('foo', function() { + chatFooSid = socket.id; + --total || getClients(); + }); + } else { + socket.join('bar', function() { + chatBarSid = socket.id; + --total || getClients(); + }); + } + }); + sio.of('/other').on('connection', function(socket){ + socket.join('foo', function() { + otherSid = socket.id; + --total || getClients(); + }); + }); + }); + function getClients() { + sio.of('/chat').in('foo').clients(function(error, sids) { + expect(error).to.be.undefined; + expect(sids).to.contain(chatFooSid); + expect(sids).to.not.contain(chatBarSid); + expect(sids).to.not.contain(otherSid); + done(); + }); + } + }); + + it('should find all clients across namespace rooms', function(done){ + var srv = http(); + var sio = io(srv); + var chatFooSid = null; + var chatBarSid = null; + var otherSid = null; + srv.listen(function(){ + var c1 = client(srv, '/chat'); + var c2 = client(srv, '/chat', {forceNew: true}); + var c3 = client(srv, '/other', {forceNew: true}); + var chatIndex = 0; + var total = 3; + sio.of('/chat').on('connection', function(socket){ + if (chatIndex++) { + socket.join('foo', function() { + chatFooSid = socket.id; + --total || getClients(); + }); + } else { + socket.join('bar', function() { + chatBarSid = socket.id; + --total || getClients(); + }); + } + }); + sio.of('/other').on('connection', function(socket){ + socket.join('foo', function() { + otherSid = socket.id; + --total || getClients(); + }); + }); + }); + function getClients() { + sio.of('/chat').clients(function(error, sids) { + expect(error).to.be.undefined; + expect(sids).to.contain(chatFooSid); + expect(sids).to.contain(chatBarSid); + expect(sids).to.not.contain(otherSid); + done(); + }); + } + }); }); describe('socket', function(){