从Nodejs socketio数组获取所有套接字id
我正在使用socketio 0.9创build一个复杂的程序,为了存储所有的套接字ID,我使用这样的数组:
var clients = {};
我正在使用自己的序列来识别我的套接字并将它们存储在我的数组中,然后设置“套接字”键以及它的实际值。
clients[serial] = { "socket": socket.id };
现在我需要从我的数组中获取所有套接字ID,而不需要它的序列号。 我该怎么做?
我正在尝试这个迭代,但我不知道如何获得套接字属性:
for(var c in clients) { c.socket }
谢谢。
这不是JavaScript中的数组
当PHP调用关联数组时 ,它只是JavaScript中的一个对象 (也称为哈希 ),以及理论计算机科学中的哈希表或散列图 。
用于…中
也就是说, for ... in
指令遍历一个对象的键 ,而不是遍历它的值 :
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"
因此,要访问你的客户端的哈希值,像socket
属性,迭代它像这样:
for (var serial in clients) { clients[serial].socket.sendSomethingViaTheSocket(...); }
那么, for ... in
似乎工作,为什么其他解决scheme甚至存在?
由于JavaScript是以原型inheritance为特征的非常dynamic的语言,因此可以添加,更改和删除几乎每个JavaScript对象的属性,并向对象原型添加新的属性和方法(某个特定方法和属性对象的“蓝图” “class”有)。
这意味着这是完全有效的JavaScript代码:
HTMLElement.prototype.isParagraph = false; HTMLParagraphElement.prototype.isParagraph = true; var myElement = document.querySelector(...); if (myElement.isParagraph) { // that's possible in javascript! }
由于扩展原型被允许用于JavaScript中的大多数对象,因此对于所有非值对象的祖先Object
原型也是可能的。 比方说,你想定义自己的方法来添加一个属性到一个对象(为什么你会决定这样做):
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
但是这意味着从现在开始JavaScript中的每个对象都有一个addProperty
方法,因此,当您使用for ... in
,将无法获得您期望的结果:
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!
您现在将会发现, for ... in
还要遍历要迭代的对象的原型链上设置的属性 。 这意味着只有在确保没有人改变原型的情况下 ,才能使用for ... in
ES5:Object.defineProperty和Object.defineProperties
自ES5以来,有两种方法来缓解这个问题。 满足Object.defineProperty
和Object.defineProperties
。 如果您需要在原型上定义方法,请使用以下方法:
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; } } );
当你定义一个可configurable: false
属性为configurable: false
,它不会出现在for ... in
循环中。
解决原型问题的解决scheme(原生JavaScript)
如果您不想使用库来解决上述问题,则可以使用包含在vanilla JavaScript中的一些方法。
Object.keys
和Array.prototype.forEach
:
Object.keys(clients).forEach(function (key) { clients[key].socket.sendSomething(); }); // will NOT iterate over prototype-inherited properties
ECMAScript2015 / ECMAScript6 for ... of
🙁 在节点4+和新浏览器中工作,没有IE)
for (let clientid of clients) { clients[clientid].socket.sendSomething(); }
//也不会迭代原型inheritance的属性
您还可以使用节点4+中的Array.prototype.map
和arrow函数以非常可读的方式获取所有客户端的套接字:
let clientSockets = Object.keys(clients).map(k => clients[k].socket); // clientSockets contains the socket of all clients now
解决原型问题的解决scheme(库)
下划线/ 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(); });
你可以创build一个你保存的所有socketId的数组:
var arr = []; Object.keys(clients).forEach(function(s){ arr.push(clients[s].socket) }); console.log(arr); // arr would have all socketIds
这里Object.keys()返回一个客户端中的所有序列的数组,然后用于迭代,并find每个socketId你保存的vaues
首先, clients
不是一个数组,而是一个对象。
你可以通过Object.keys()
获得所有密钥,或者从lodash
获得一些帮助,你可以使用_.keys
或者如果你只对socket id感兴趣:
let _ = require('lodash'); console.log(_.map(clients, 'socket');