3

I'm trying to interrogate if any of the clients in a room have a particular property associated with them. The async nature of the socket.io get method is causing me problems. I've seen the async library, which looks like it might be what I need, but I'm having difficulties visualising how to apply that to this situation.

Here is how I'd like the function to work, assuming the get wasn't async;

/**
*
**/
socket.on('disconnect', function(data) {
  socket.get('room', function(err, room) {
    if(!roomHasProperty(room)) {
      io.sockets.in(room).emit('status', { message: 'property-disconnect' });
    }
  }); 
});

/**
*
**/
var roomClients = function(room) {
  var _clients = io.sockets.clients(room);
  return _clients;
}

/**
*
**/
var roomHasProperty = function(room) {
  // get a list of clients in the room
  var _clients = roomClients(room);
  // build up an array of tasks to be completed
  var tasks = [];
  // loop through each socket in the room
  for(key in _clients) {
    var _socket = _clients[key];
    // grab the type from the sockets data store and check for a control type
    _socket.get('type', function (err, type) {
      // ah crap, you already went ahead without me!?
      if(type == 'property') {
          // found a the property type we were looking for
          return true;
      }
    });
  }
  // didn't find a control type
  return false;
}

Is there a better way of doing this?

Dan Steele
  • 1,644
  • 3
  • 13
  • 13
  • Aside from the async issue, I've just noticed that I'm returning true in the callback and not the parent method. Fool. – Dan Steele May 09 '13 at 11:03

1 Answers1

0

Have you considered using a promises library? It makes dealing with async functions a lot easier. If you were to use Q, you could do this: (I'm sorry, i can't check the code right now, but I'm pretty sure it should work almost with no changes)

var roomHasProperty = function(room) {
  // Create the deferred object
  var deferred = Q.defer(); 
  // get a list of clients in the room
  var _clients = roomClients(room);
  // array of promises to check
  var promises = [];

  // This function will be used to ask each client for the property
  var checkClientProperty = function (client) {
    var deferred = Q.defer();
    // grab the type from the sockets data store and check for a control type
    client.get('type', function (err, type) {
      // ah crap, you already went ahead without me!?
      if(type == 'property') {
        // found a the property type we were looking for
        deferred.resolve(true);
      } else {
        // property wasn't found
        deferred.resolve(false);
      }
    });
    return deferred.promise;
  }
  // loop through each socket in the room
  for(key in _clients) {
    promises.push(checkClientProperty(_clients[key]));
  }
  Q.all(promises).then(function (results) {
    deferred.resolve(results.indexOf(true) > -1);
  })
  // didn't find a control type
  return deferred.promise;
}

You can use this like this:

checkClientProperty(client).then(function (result) {
  if (result) {
    console.dir('the property was found');
  } else {
    console.dir('the property was not found');
  }
});
Ezequiel
  • 405
  • 5
  • 8