walolinux
walolinux

Reputation: 551

Getting all sockets id from Nodejs socketio array

I am using socketio 0.9 to create a complex program and in order to store all the sockets id, i am using arrays like this:

var clients = {};

I am using my own serial to identify my sockets and store them in my array, and then i am setting the 'socket' key, with its real value.

clients[serial] = { "socket": socket.id };

Now i need to get all sockets id from my array without its serial. How can i do it?

I am trying with this iteration, but i donw know how to get the socket atribute:

for(var c in clients) {
c.socket
}

Thanks.

Upvotes: 1

Views: 1212

Answers (3)

crackmigg
crackmigg

Reputation: 5881

First of all, clients is not an array but an object.

You can get all keys with Object.keys() or with a little help from lodash you can use _.keys or if you are only interested in the socket ids:

let _ = require('lodash');

console.log(_.map(clients, 'socket');

Upvotes: 0

Leon Adler
Leon Adler

Reputation: 3331

That's not an array in JavaScript

While PHP calls that an associative array, it is just an object (also called hash) in JavaScript, and a hash table or hash map in theoretical computer science.

Using for ... in

That being said, the for ... in instruction iterates over the keys of an object, not over its values:

var clients = {
  clientid1: { name: "John Doe", age: 42 },
  clientid2: { name: "Jane Doe", age: 34 }
};

for (var key in clients) {
  console.log(key);
}
Console output:
  "clientid1"
  "clientid2"

Therefore, to access the values of your clients hash, like the socket property, iterate it like this:

for (var serial in clients) {
  clients[serial].socket.sendSomethingViaTheSocket(...);
}

Well, for ... in seems to work, why do other solutions even exist?

Since JavaScript is a very dymanic language featuring prototypal inheritance, you can add, change, and remove properties of pretty much every JavaScript object, and add new properties and methods to object prototypes (the "blueprint" of what methods and properties objects of a certain "class" have).

This means that this is fully valid JavaScript code:

HTMLElement.prototype.isParagraph = false;
HTMLParagraphElement.prototype.isParagraph = true;

var myElement = document.querySelector(...);
if (myElement.isParagraph) {
  // that's possible in javascript!
}

Since extending the prototype is allowed for most objects in JavaScript, it is also possible for the Object prototype, which is the ancestor for all non-value objects. Let's say you want to define your own method for adding a property to an object (why ever you would decide to do this):

Object.prototype.addProperty = function (name, value) {
  this[name] = value;
};

var exampleCustomer = { name: "John Doe" };
exampleCustomer.addProperty("age", 42);
console.log(exampleCustomer.age);    // logs 42 on the console

But this means that every object in JavaScript from now on has a addProperty method, therefore when you use for ... in, you will not get the result you expect:

for (var key in exampleCustomer) {
  console.log('key ', key, ' equals ', exampleCustomer[key]);
}
Console output:
  key name equals John Doe
  key age equals 42
  key addProperty equals function (name, value) { ... }
       ^ oops!

You will now find that for ... in also iterates over properties set on the prototype chain of the object you want to iterate over. This means that using for ... in is fine if, and only if, you can be sure that nobody alters your prototypes.

ES5: Object.defineProperty and Object.defineProperties

Since ES5, there exist two methods to mitigate that problem. Meet Object.defineProperty and Object.defineProperties. Should you ever need to define methods on prototypes, use these methods:

Object.defineProperty(
  Object.prototype, // the object the property should be defined on
  "addProperty", // name of the property
  {
    enumerable: false, // should the property show up in for ... in / Object.keys()?
    writable: true, // can the value of this property be changed with obj.addProperty = ..?
    configurable: true, // can this property be changed with another defineProperty call?
    value: function (name, value) { this[name] = value; }
  }
);

When you define a property with configurable: false, it will not show up in a for ... in loop.

Solutions that work around the prototype issues (native JavaScript)

If you don't want to use a library to work around the problems described above, you can use some methods included in vanilla JavaScript.

Object.keys and Array.prototype.forEach:

Object.keys(clients).forEach(function (key) {
  clients[key].socket.sendSomething();
});
// will NOT iterate over prototype-inherited properties

ECMAScript2015/ECMAScript6 for ... of: (works in node 4+ and new browsers, no IE)

for (let clientid of clients) {
  clients[clientid].socket.sendSomething();
}

// also does NOT iterate over prototype-inherited properties

You can also use Array.prototype.map and arrow functions in node 4+ to get the sockets of all clients in a very readable way:

let clientSockets = Object.keys(clients).map(k => clients[k].socket);
// clientSockets contains the socket of all clients now

Solutions that work around the prototype issues (libraries)

Underscore / lodash:

_.each(clients, function (client) {
  client.socket.sendSomething();
});

jQuery:

$.each(clients, function (id, client) {
  client.socket.something();
});

AngularJS:

angular.forEach(clients, function (client, id) { // order is different than with jQuery!
  client.socket.something();
});

Upvotes: 1

Nijeesh
Nijeesh

Reputation: 847

You can create an array of all socketIds you saved like this :

var arr = [];
Object.keys(clients).forEach(function(s){
    arr.push(clients[s].socket)    
});
console.log(arr); // arr would have all socketIds

Here Object.keys() returns an array of all serials in clients which is then used to iterate and find each socketId vaues you saved

Upvotes: 0

Related Questions