简体   繁体   中英

Connected clients in express.io

I'm developing a simple chat app using node.js and express.io

I would like to display a list of the connected clients (or online for chat) all the time.

In express.io's doc , there is no clear way on how to "get" the list of connected clients once a new one has entered the room, ie there is just the "broadcast" but not the "get".

Have someone done this before?

Any clues will be really helpful.

Thanks!

Edit:

After trying @jibsales's answer. I think we are almost there. What clients returns me is not the actual array of clients but this one:

[ { id: 'OWix3sqoFZAa20NLk304',
namespace: 
 { manager: [Object],
   name: '',
   sockets: [Object],
   auth: false,
   flags: [Object],
   _events: [Object] },
manager: 
 { server: [Object],
   namespaces: [Object],
   sockets: [Object],
   _events: [Object],
   settings: [Object],
   handshaken: [Object],
   connected: [Object],
   open: [Object],
   closed: [Object],
   rooms: [Object],
   roomClients: [Object],
   oldListeners: [Object],
   sequenceNumber: 496205112,
   router: [Object],
   middleware: [],
   route: [Function],
   use: [Function],
   broadcast: [Function],
   room: [Function],
   gc: [Object] },
disconnected: false,
ackPackets: 0,
acks: {},
flags: { endpoint: '', room: '' },
readable: true,
store: { store: [Object], id: 'OWix3sqoFZAa20NLk304', data: {} },
_events: 
 { error: [Function],
   ready: [Function],
   connection: [Function],
   NewChatPrivateLine: [Function],
   NewIdea: [Function],
   NewChatLine: [Function],
   NewPost: [Function] } } ]

The functions are:

var app = require('express.io')();
app.io.route('connection', function(req) {
  req.io.join(req.data.room);
  var clients = app.io.sockets.clients(req.data.room);
  console.log(clients)
  app.io.room(req.data.room).broadcast('announce', {
    user: req.data.user,
    clients: clients
  }) 
});

This actually returns an error ( data = JSON.stringify(ev); TypeError: Converting circular structure to JSON) as the array has several circular objects and hence it cannot be broadcasted.

Any thoughts?

Because express.io is simply glueing express and socket.io , don't forget to look at socket.io 's documentation as well. With that said, since socket.io v0.7, we now have an API method to get this information:

var clients = io.sockets.clients('room'); // all users from room `room`

Unfortunately express.io is written in coffeescript (UGGGH!!!) so I'm having a hard time reading the source, but it looks like when you require the express.io module, the socket.io instance is hoisted up as well:

var express = require('express.io');
var clients = express.io.sockets.clients('room'); // all users from room `room`

If this doesn't work, I would ditch express.io for a manual configuration with express and socket.io because it looks like express.io has a VERY opinionated API. Its really not that hard at all as express.io is doing nothing more than creating a pretty interface/abstraction to manual configuration (which is actually hurting you in this use case if the above doesn't work).

I would also checkout SockJS as I (and many other websocket consumers) ditched socket.io for SockJS due to a lack of community support. Not to mention, there is a SEVERE memory leak in IE9 when falling back to xhr-polling.

Well, finally I went with the "tacking" solution proposed by @Brad. It is not the most elegant but, if you can help me improve it, It'd be awesome!!

This is the final code:

Server-side

var app = require('express.io')();

//To broadcast the users online in room sent by the client
var clients = [];
app.io.route('connect', function (req) {
  req.io.leave(req.data.room).on('disconnect', function() {
    //To remove client from list when disconnected
    var index = clients.indexOf(req.data.user);
    if (index > -1) {
      clients.splice(index, 1);
    }
    app.io.room(req.data.room).broadcast('announce', {
      user: req.data.user,
      clients: clients
    }) 
  });
  req.io.join(req.data.room);
  //To avoid repeating the same client with several opened windows/tabs
  var index = clients.indexOf(req.data.user);
  if (index === -1) {
    clients.push(req.data.user); 
  }
  app.io.room(req.data.room).broadcast('announce', {
    user: req.data.user,
    clients: clients
  }) 
});

Client-side

// Emit ready event with person name and predefined room for who's online
io.emit('connect', {
  room: room,
  user: user
});

//Get the signal from server and create your list
io.on('announce', function (data){
 //Do awesome stuff with data 
}); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM